BigInteger.isProbablePrime 似乎比它说的要确定得多

BigInteger.isProbablePrime seems much more certain than it says it is

我理解 certainty 参数的意思是:

certainty - a measure of the uncertainty that the caller is willing to tolerate: if the call returns true the probability that this BigInteger is prime exceeds (1 - 1/2certainty)

从我的实验来看,它似乎超过了很多!下面的代码找到 2 到 100 万之间的“可能素数”,并检查一组确定的素数以查看它是否是误报。

我使用的确定性参数为 2。因此我预计只有 75% 的“可能素数”将是实际素数。 (1 - 1/22 = 0.75 = 75%.)

实际上,它在 99.9% 的时间里都是正确的。

我对“确定性”的理解正确吗?我怀疑如果我在实验中看到的确定性超出我的预期那么多。

import java.math.BigInteger;
import java.util.BitSet;

import static java.lang.Math.sqrt;

public class PrimesCalculator {
    public final int max;
    private final BitSet sieve;  // Set of all non-primes from 2 to max.

    public PrimesCalculator(int max) {
        this.max = max;
        sieve = new BitSet(max+1);
        for (int n = 2, sqrtMax = (int) sqrt(max); n < sqrtMax; n++)
            for (int i = n * 2; i < max; i += n)
                sieve.set(i);
    }

    public boolean isPrime(int n) {
        return !sieve.get(n);
    }

    public static void main(String[] args) {
        PrimesCalculator calc = new PrimesCalculator(1_000_000);
        int numPrimes = 0;
        int numProbablePrimes = 0;
        for (int i = 2; i < calc.max; i++)
            if (BigInteger.valueOf(i).isProbablePrime(2)) {
                numProbablePrimes++;
                if (calc.isPrime(i))
                    numPrimes++;
            }
        System.out.printf("%s/%s (%s%%)%n", numPrimes, numProbablePrimes, numPrimes / (numProbablePrimes / 100.0));
    }
}

您引用的文档是正确的。

certainty - a measure of the uncertainty that the caller is willing to tolerate: if the call returns true the probability that this BigInteger is prime exceeds (1 - 1/2certainty)

99.9% 确实超过了 1 - 1/(22) = 3/4,所以你向我们展示的没有任何问题。

该实现不保证 恰好是 的概率,它只是提供了一个实现,其误差是 绝对受限 的。

大多数质量素性测试程序都会对小素数进行大量优化,或者更确切地说,其除数是小合数的数字。这些可能会在算法的随机方面之前启动,从而导致 higher-than-usual 小素数的准确性。

这些陈述经常引起混淆。我会尝试在这里更好地解释它。

Java 的 BigInteger.isProbablePrime() 根本不包含对小整数的优化,除了 0、1 和 2 被视为特殊情况并且除 2 之外的所有偶数整数都立即声明为复合。

使用 Miller-Rabin (MR) 素性测试检查所有其他奇数的素性。此外,如果整数是 100 位或更大,还会使用称为 Lucas-Lehmer 测试的东西对其进行检查。

MR 是一个复杂的素数测试,其解释和分析超出了 SO 答案的范围。关键是,就 MR 而言,并非所有复合材料都生而平等。非常非常小的一部分很难发现它们的复合性。举几个例子:在小奇数组合中,91、703 和 1891 是困难的。 MR 通过尝试多次随机尝试来发现整数的复合性来克服这个问题。 Rabin 的分析表明,对于表现最差的复合材料,单次随机尝试仍有至少 75% (3/4) 的概率揭示其复合材料。

certainty 参数几乎等同于指定 MR 算法需要执行的随机尝试次数。实际上,certainty参数与随机尝试次数的关系比较复杂,我自己也不是很明白。

作为查看不同复合材料性能的实验,请将您的程序更改为只是反复尝试确认 1891 年的复合材料。您会看到接近 75% 的成功率。

MR-stubborn 个相对较小的复合材料列表是 here