我想使用nextProbablePrime()
方法BigInteger
来获得低于给定数字而不是更高的素数。
是否可以只使用一个电话来获得它nextProbablePrime
?
我想使用nextProbablePrime()
方法BigInteger
来获得低于给定数字而不是更高的素数。
是否可以只使用一个电话来获得它nextProbablePrime
?
我不知道是否可以使用该nextProbablePrime
方法(一次调用)。但是,我只是需要一个previousProbablePrime
方法,我想出了以下使用API中的isProbablePrime
方法的方法:BigInteger
public static BigInteger previousProbablePrime(BigInteger val) {
// To achieve the same degree of certainty as the nextProbablePrime
// method, use x = 100 --> 2^(-100) == (0.5)^100.
int certainty = 100;
do {
val = val.subtract(BigInteger.ONE);
} while (!val.isProbablePrime(certainty));
return val;
}
我设置了以下测试只是为了比较该nextProbablePrime
方法的速度(和准确性):
private static void testPreviousProbablePrime() {
BigInteger min = BigInteger.ONE; // exclusive
BigInteger max = BigInteger.valueOf(1000000); // exclusive
BigInteger val;
// Create a list of prime numbers in the range given by min and max
// using previousProbablePrime method.
ArrayList<BigInteger> listPrev = new ArrayList<BigInteger>();
Stopwatch sw = new Stopwatch();
sw.start();
val = BigIntegerUtils.previousProbablePrime(max);
while (val.compareTo(min) > 0) {
listPrev.add(val);
val = BigIntegerUtils.previousProbablePrime(val);
}
sw.stop();
System.out.println("listPrev = " + listPrev.toString());
System.out.println("number of items in list = " + listPrev.size());
System.out.println("previousProbablePrime time = " + sw.getHrMinSecMsElapsed());
System.out.println();
// Create a list of prime numbers in the range given by min and max
// using nextProbablePrime method.
ArrayList<BigInteger> listNext = new ArrayList<BigInteger>();
sw.reset();
sw.start();
val = min.nextProbablePrime();
while (val.compareTo(max) < 0) {
listNext.add(val);
val = val.nextProbablePrime();
}
sw.stop();
System.out.println("listNext = " + listNext.toString());
System.out.println("number of items in list = " + listNext.size());
System.out.println("nextProbablePrime time = " + sw.getHrMinSecMsElapsed());
System.out.println();
// Compare the two lists.
boolean identical = true;
int lastIndex = listPrev.size() - 1;
for (int i = 0; i <= lastIndex; i++) {
int j = lastIndex - i;
if (listPrev.get(j).compareTo(listNext.get(i)) != 0) {
identical = false;
break;
}
}
System.out.println("Lists are identical? " + identical);
}
该类Stopwatch
只是一个用于跟踪执行时间的基本自定义类,因此请修改这些部分以适合您可能拥有的类。
我测试了从 1 到 10000、100000 和 1000000 的范围previousProbablePrime
。在所有三个测试中执行该方法的时间都更长。然而,执行时间的差异似乎仅随着范围大小每增加 10 倍而适度增加。对于 10000,previousProbablePrime
在不到一秒的时间内执行,而nextProbablePrime
在大约 200 毫秒时执行,相差大约 700 或 800 毫秒。对于 1000000,差异仅为 2 秒左右,尽管执行时间分别为 9 秒和 7 秒。结论,执行时间的差异比范围大小增加得慢。
在所有测试中,这两个列表包含相同的质数集。
这种效率水平足以满足我的需求……也可能对您有用。
编辑
修改了方法实现以提高效率并且可能更快,尽管我没有测试过。
public static BigInteger previousProbablePrime(BigInteger val) {
if (val.compareTo(BigInteger.TWO) < 0) {
throw new IllegalArgumentException("Value must be greater than 1.");
}
// Handle single unique case where even prime is returned.
if (val.equals(new BigInteger("3"))) {
return BigInteger.TWO;
}
// To achieve the same degree of certainty as the nextProbablePrime
// method, use x = 100 --> 2^(-100) == (0.5)^100.
int certainty = 100;
boolean isEven = val.mod(BigInteger.TWO).equals(BigInteger.ZERO);
val = isEven ? val.subtract(BigInteger.ONE) : val.subtract(BigInteger.TWO);
while (!val.isProbablePrime(certainty)) {
// At this point, only check odd numbers.
val = val.subtract(BigInteger.TWO);
}
return val;
}