1

I wrote two methods to test wheter a BigInteger is a prime or not. I start with (2^64)+1 and then I always add 2 until I find a prime. These are the two methods:

public static boolean isPrime(BigInteger n) {

    BigInteger max_long = BigInteger.valueOf(Long.MAX_VALUE);       
    if (n.compareTo(max_long)<=0) return isPrime(n.longValue());

    final BigInteger two = new BigInteger ("2");

    if ((n.mod(two)).compareTo(BigInteger.ZERO)==0) return false;

    else {
        for (BigInteger i=new BigInteger ("3"); i.multiply(i).compareTo(n)<=0; i=i.add(two)) {
            if((n.mod(i)).compareTo(BigInteger.ZERO)==0) return false;
        }
    }
    return true;
}

The other one is:

public static boolean isPrimeImproved (BigInteger n) {
    BigInteger max_long = BigInteger.valueOf(Long.MAX_VALUE);
    if(n.compareTo(max_long)<=0) return isPrime(n.longValue());

    final BigInteger two = new BigInteger("2");
    if(n.mod(two).compareTo(BigInteger.ZERO)==0) return false;

    else {
        for(BigInteger i=new BigInteger("3"); i.multiply(i).compareTo(n)<=0; i=i.nextProbablePrime()) {
             if(n.mod(i).compareTo(BigInteger.ZERO)==0) return false;
        }       
    }
    return true;

}

The first one terminates after around 310 seconds. But the second one doesn't seem to terminate, although it should be faster, shouldn't it? And I know, that there is a method called isProbablePrime(), but I mustn't use it.

Tim Buchholz
  • 83
  • 1
  • 3
  • 10

1 Answers1

3

Both your for loops require a BigInteger multiplication each time through the loop: i.multiply(i).compareTo(n)<=0; Given that we are working above Long.MAX_VALUE then that is a lot of expensive multiplications. It would probably be faster to do a single square root calculation to find a fixed limit for the loop: i.compareTo(iSqrt)<=0;

It is easy enough to write a simple piece of Newton-Raphson code to find an integer square root. It will only be run once, and will replace a great many expensive multiplications. Crandall and Pomerance give a version and I am sure there are other versions out there.

rossum
  • 15,344
  • 1
  • 24
  • 38
  • It is indeed quite simple. My (non-Java) BigInteger uses a simple algorithm similar to Newton-Raphson to find any nth root and it works fine. And precalculating the square root would indeed make things quite a bit faster, although perhaps not as much as expected. – Rudy Velthuis Mar 27 '17 at 11:15