我知道在实践中使用了许多素性测试算法(Eratosthenes的Sieve,Fermat的测试,Miller-Rabin,AKS等)。然而,它们要么是缓慢的(例如筛子),要么是概率的(Fermat和Miller-Rabin),要么是相对难以实施的(AKS)。
确定数字是否为素数的最佳确定性解决方案是什么?
请注意,我主要(双关语)有兴趣测试大约32位(也许是64位)的数字。因此,不需要一个强大的解决方案(适用于更大的数字)。
答案 0 :(得分:11)
最多~2^30
你可以通过试验分裂来蛮力。
最多3.4*10^14
,Rabin-Miller with the first 7 primes has been proven to be deterministic。
在上面,你是独立的。没有已知的亚立方确定性算法。
编辑:我记得这一点,但直到现在我才找到参考资料:
http://reference.wolfram.com/legacy/v5_2/book/section-A.9.4
PrimeQ首先使用小素数测试可分性,然后使用 Miller-Rabin强力假试验基地2和基地3,然后使用 卢卡斯考试。
截至1997年,已知此程序仅适用于
n < 10^16
, 并且可以想象,对于较大的n
,它可以声称合成 数字是素数。
因此,如果你实施Rabin-Miller和Lucas,你可以达到10 ^ 16 。
答案 1 :(得分:3)
如果我不关心空间,我会尝试预先计算2 ^ 32以下的所有素数(~4e9 / ln(4e9)* 4字节,小于1GB),将它们存储在内存中并使用二分搜索。您还可以使用包含这些预先计算的素数的文件的内存映射(优点:更快的程序启动,缺点:在所有需要的数据实际存在于内存中之前会很慢)。
答案 2 :(得分:2)
如果你可以考虑 n -1,那么使用Edouard Lucas在19世纪开发的方法很容易证明 n 是素数。您可以在Wikipedia阅读有关算法的信息,或者查看我在my blog处的算法实施情况。算法的变体只需要部分分解。
如果 n -1的因子分解很困难,那么最好的方法是elliptic curve primality proving算法,但这需要更多的数学运算和更多的代码,而不是你愿意写的。无论如何,这比AKS要快得多。
您确定需要绝对的素数证明吗? Baillie-Wagstaff algorithm比任何确定性素性证明者都快,并且没有已知的反例。
如果你知道 n 永远不会超过2 ^ 64,那么使用first twelve primes作为基础的强伪素数测试足以证明 n 素数。对于32位整数,对三个基数2,7和61的强伪测试足以证明素数。
答案 3 :(得分:1)
使用Eratosthenes筛选预先计算尽可能多的素数。你可以在每个数字的一个位上装入很多,并通过仅筛选奇数来将空间减半(将2视为特殊情况)。
对于从Sieve.MAX_NUM
到Sieve.MAX_NUM
的平方的数字,您可以使用试验分区,因为您已经列出了所需的素数。在较大的无因素残留物上明智地使用Miller-Rabin可以大大加快这一过程。
对于大于我的数字,我会使用其中一个概率测试,Miller-Rabin是好的,如果重复几次就可以得到比计算机硬件故障更不容易出错的结果运行。