Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - Mersenne Prime assignment

Tags:

java

the assignment is to find all Mersenne primes with p <= 31 and display in a table:

p     2^p-1
---   ---- 
2      3

3      7

5      31

...

My result so far is this code:

public class PE28MersennePrimeVer2 {

    public static void main(String[] args) {

        System.out.println("p\t2^p - 1");

        for (int number = 2; number <= 31; number++) {
            if (isPrime(number)) {
                int mersennePrime = (int)(Math.pow(2, number)) - 1;
                if (isPrime(mersennePrime)) {
                    System.out.print(number + "\t" + mersennePrime + "\n");
                }
            }
        }
    }

    public static boolean isPrime(int number) {

        if ((number == 1) || (number == 2)) {
            return true;
        }

        for (int i = 2; i <= number/2; i++) {
            if (number % i == 0) {
                return false;
            }
        }

        return true;
    }
}

The output is for p up to 19, never reach 31. What I'm doing wrong?

like image 236
venta7 Avatar asked Oct 31 '25 00:10

venta7


1 Answers

The problem is that

(int)Math.pow(2,31) - 1;

evaluates to 2147483646 instead of 2147483647.

Don't use floating point math when dealing with integers. In Java, using (1 << number) - 1 works (1 << 31 would be undefined behaviour in C due to overflow, but it's defined in Java).

If you cannot use bit-shifts, you can write your own integer-power function. For the small exponents under consideration, the straightforward

long pow(long base, long exponent) {
    long result = 1;
    while(exponent > 0) {
        result *= base;
        --exponent;
    }
}

is good enough (note: I used long instead of int to avoid overflows; although the overflow behaviour is defined in Java, avoiding overflow is cleaner).

With that,

mersennePrime = (int)(pow(2,number) - 1);

does its job (although you should consider using long also for the other variables, not only for the intermediate pow result).

For larger exponents (although that would only be relevant for using BigIntegers - which have their own implementation in the standard library - or modular exponentiation), exponentiation by repeated squaring

long pow(long base, long exponent) {
    long aux = 1;
    while(exponent > 0) {
        if (exponent % 2 == 1) {
            aux *= base;
        }
        base *= base;
        exponent /= 2;
    }
    return aux;
}

would give a big performance advantage.

like image 123
Daniel Fischer Avatar answered Nov 02 '25 13:11

Daniel Fischer