我写了两种方法来测试BigInteger是否是素数。我从(2 ^ 64)+1开始,然后我总是加2,直到我找到一个素数。这是两种方法:
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;
}
另一个是:
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;
}
第一个在大约310秒后终止。但第二个似乎没有终止,虽然它应该更快,不应该吗? 我知道,有一个名为isProbablePrime()的方法,但我不能使用它。
答案 0 :(得分:3)
每次循环时,for
循环都需要BigInteger
次乘法:i.multiply(i).compareTo(n)<=0;
鉴于我们的工作时间超过Long.MAX_VALUE
,那么批次< / em>昂贵的乘法。进行单个平方根计算以找到循环的固定限制可能会更快:i.compareTo(iSqrt)<=0;
编写一段简单的Newton-Raphson代码来查找整数平方根很容易。它只会运行一次,并将取代许多昂贵的乘法。 Crandall和Pomerance给出了一个版本,我相信还有其他版本。