0

It is a code that gets prime numbers, I have made it as efficient as I could, but the problem is that I can't transform it to BigInteger, as long can't hold that much information; here the code:

public class p3{
    static long perfectNumber;
    static long mersenne;

    public static void main(String[] args) {
        long p = 2;
        while (true) {
            if( p % 2 == 0&&p!=2){
                p++;
            }
            else{
                if (isPrime(p) == true) {
                    mersenne = (long) (Math.pow(2, p) - 1);
                    if (isPrime(mersenne) == true) {
                        perfectNumber = (long) Math.pow(2, (p - 1)) * mersenne;
                        System.out.println(perfectNumber);
                    }
                }
                p+=1;
            }
        }
    }
    private static boolean isPrime(long testPrime) {
        for (long i = 3; i < Math.sqrt(testPrime); i += 2) {
            if (testPrime % i == 0) {
                    return false;
            }
        }
        return true;
    }
}
A Mm
  • 1
  • 1
    What issue you are having? – Yoshikage Kira Oct 01 '19 at 23:53
  • 2
    Did you take a look at its documentation? [BigInteger](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/math/BigInteger.html) – Yoshikage Kira Oct 01 '19 at 23:56
  • 3
    First the issue isn't that long can't hold enough information. It can hold 19 digits which is over 100,000 trillion. There isn't enough time to calculate primes of that magnitude using your algorithm or even a sieve. However, using `BigInteger` will let you use the sophistcated `isProbablePrime` method . So read the suggested documentation and just make the simple changes. – WJS Oct 02 '19 at 00:00
  • @Goion I need to transform this to BigInteger as long are not enough for Perfect Numbers – A Mm Oct 02 '19 at 23:23
  • @WJS I've tried to use BigInteger but code is not working, as I can't use BigInteger exponents with pow. – A Mm Oct 02 '19 at 23:25
  • 1
    Pay attention to what WJS wrote. Your `isPrime()` method will take forever before `p` is larger than a single byte, let alone a long. The largest known mersenne prime is for p = 82,589,933. – President James K. Polk Oct 03 '19 at 00:16

1 Answers1

1

I've tried to use BigInteger but code is not working, as I can't use BigInteger exponents with pow

You don't need to. The exponents don't need to be nearly as large as the mersenne primes and perfect numbers. They can have their own independent isPrime() test. In fact, they need to be int, instead of long, to satisfy BigInteger.pow().

Below is what you asked for, but may not be what you want. I doubt you'll get more then one additional perfect number beyond your original code due to time constraints which is why @WJS is pushing you in a different direction.

import java.math.BigInteger; 

public class p3 {
    static BigInteger TWO = new BigInteger("2");
    static BigInteger THREE = new BigInteger("3");

    public static void main(String[] args) {
        int p = 2;

        while (true) {
            if (isPrime(p)) {
                BigInteger mersenne = TWO.pow(p).subtract(BigInteger.ONE);

                if (isPrime(mersenne)) {
                    System.out.println(TWO.pow(p - 1).multiply(mersenne));
                }
            }

            p += (p == 2) ? 1 : 2;
        }
    }

    private static boolean isPrime(BigInteger number) {
        if (number.mod(TWO).equals(BigInteger.ZERO)) {
            return number.equals(TWO);
        }

        for (BigInteger i = THREE; number.compareTo(i.multiply(i)) >= 0; i = i.add(TWO)) {
            if (number.mod(i).equals(BigInteger.ZERO)) {
                return false;
            }
        }

        return true;
    }

    private static boolean isPrime(int number) {
        if (number % 2 == 0) {
            return number == 2;
        }

        for (int i = 3; number >= i * i; i += 2) {
            if (number % i == 0) {
                return false;
            }
        }

        return true;
    }
}

OUTPUT

> java p3
6
28
496
8128
33550336
8589869056
137438691328
2305843008139952128
2658455991569831744654692615953842176

Your original code outputs 0 in place of the final (37 digit) number above. So the immediate issue really is that long can't hold enough information. But beyond this point, you simply can't calculate fast enough with the above algorithm.

If we do something simple-minded to my above code, like replace this line:

 if (isPrime(mersenne)) {

with:

if (mersenne.isProbablePrime(10)) {

The code will spit out the first 20 perfect numbers before slowing to a crawl. Tune the certainty argument of isProbablePrime() as you see fit.

cdlane
  • 40,441
  • 5
  • 32
  • 81