如何找到与证明素数之一:小素数和概率素数的快速检验

  • 引言
  • 一、寻找十分小的素数
  • 二、费马数,概率素数和伪素数
  • 三、强概率素性检验

引言

在前一篇文章中,我们对如何寻找素数给出了三类方法,本文则详细讨论前篇文章的第一节内容。首先是一个简短的介绍和目录。本章讨论寻找小素数和基本的概率素性检验


一、寻找十分小的素数

为了找到所有的小素数,比如小于 10,000,000,00010,000,000,00010,000,000,000 的素数,最有效的方法之一是使用埃拉托色尼筛法 ( 公元前 240 年 ):

列出所有小于或等于 nnn ( 大于 111 ) 的整数,去掉所有小于或等于根号 nnn 的素数的倍数,剩下的数就是素数。

例如,要找出所有小于或等于 100100100 的奇素数,我们首先列出从 333 到 100100100 的奇数,第一个数是 333,所以它是第一个奇素数,把它的倍数都划掉。剩下的第一个数是 555,即第二个奇素数,把它的倍数都划掉。重复到 777 后,因为剩下的第一个数 111111 大于 100100100 的平方根,所以剩下的所有数都是素数。

这种方法非常快,以至于没有理由在计算机上存储大量的素数列表——如此高效的实现可以比计算机从磁盘读取素数的速度更快地找到它们。

Bressoud 有这个算法的伪代码实现 [Factorizations and primality testing, 1989, p19],Riesel 有一个 PASCAL 实现 [Prime numbers and computer methods for factorization, 1994, p6]。也可以基于二次形创建更快的筛法。

如果找小素数,试除法效果会很好。要检验 nnn 是否是素数,只需除以所有小于 n\sqrt{n}n​ 的素数。例如,要验证 211211211 是不是素数,只需除以 2、3、5、7、112、3、5、7、112、3、5、7、11 和 131313 。( 伪代码 [Bressoud, Factorizations and primality testing, pp 21-22], PASCAL [Prime numbers and computer methods for factorization, pp 7-8] )。有时数字 nnn 的形式使这种方法特别有效 ( 例如,梅森数的因子有一种特殊的形式 )。

与其只除以素数,有时除以 2,32, 32,3 和 555 更实用;然后除以对 30(=2⋅3⋅5)30 \;(=2\cdot3\cdot5)30(=2⋅3⋅5) 取模等于:
1,7,11,13,17,19,23,291, 7, 11, 13, 17, 19, 23, 291,7,11,13,17,19,23,29的所有整数,同样在取到平方根时停止。这种类型的分解有时称为轮式分解 ( wheel factorization )。它需要更多的除法 ( 因为一些除数是合数 ),但不需要我们有一个可用的素数列表。我们将模 303030 的余数 1,7,11,13,17,19,23,291, 7, 11, 13, 17, 19, 23, 291,7,11,13,17,19,23,29 称为轮辐 ( spokes ) 。

例如我们要用上面提到的轮式分解来判断 333133313331 是否是素数,我们要除以 2、3、5、7、11、13、17、19、23、29、31、37、41、43、47、492、3、5、7、11、13、17、19、23、29、31、37、41、43、47、492、3、5、7、11、13、17、19、23、29、31、37、41、43、47、49 和 535353 。注意 494949 不是素数,但相对于轮式分解来说是素数 ( 不妨称这组数为轮式分解素数 ) 。前面的 2,3,52,3,52,3,5 是 303030 的因数,需要人为添上。

轮式分解其实是一种特殊类型的筛法。

( wheels ) 可以做成任何尺寸。最简单的轮是用一个素数 222 来创造的,同时有一条轮辐:111 ( 所以我们要除以 222 ,然后取每个奇数 )。稍微复杂一点的轮会使用素数 222 和 333 。这样我们就有了两条轮辐:1 和 5 ( 模 666 的余数,因 2,32,32,3 被用到,故此处不能出现 ) 。所以我们要除以下面的整数:
2,3,5,7,11,13,17,19,23,25,29,31,35,37,41,43,⋯2,3,5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, \cdots2,3,5,7,11,13,17,19,23,25,29,31,35,37,41,43,⋯ 前面的 2,32,32,3 是 666 的因数,需要人为添上。

这与将整数写在宽度为 666 的表中是一样的——所有素数 ( 除了 222 或 333 ) 最后都在与两个轮辐 111 和 555 对应的列中。( 素数用绿色表示 )

如果我们从素数 2,3,5,72, 3, 5, 72,3,5,7 开始,然后检查对 210 ( 这四个素数的乘积 ) 取模的余数是否与如下轮辐一致:

1, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 121, 127, 131, 137, 139, 143, 149, 151, 157, 163, 167, 169, 173, 179, 181, 187, 191, 193, 197, 199, 209. ( 121, 143, 169, 187, 209 为真正意义的合数 )

请注意,除了 111 之外,轮中这些最小的轮辐都是素数 ( 轮式分解素数 ) 。这是因为任何小于轮中使用的最大素数的平方的数都必须是素数,而不是轮所除去的 ( 轮中使用的数是指一个整数 nnn 除以轮辐中其平方小于 nnn 的那些轮辐 )。然而这也误导过许多人,认为这样的轮是素数的良好“生成器”。但事实并非如此,素数的密度会随着整数大小的增加而减小 ( 参见素数定理 ),因此当我们将这些相同的轮应用于一个大的整数列表时,几乎所有没有被轮排除的数都是合数。

基于 222 和 333 的简单轮排除了 4/6=2/34/6 = 2/34/6=2/3 的合数。使用 2、3、52、3、52、3、5 和 777 的较复杂轮将去除 162/210162/210162/210 ( 超过 77%77\%77% ) 的合数。

复杂轮的效率不是特别高。要去除 90%90\%90% 的合数,我们必须使用 251251251 以内的素数。95%95\%95% 要求素数直到 750377503775037。96%96\%96% 要求素数直到 124637912463791246379 。97%97\%97% 要求素数直到 134253593134253593134253593 !想象一下,你需要多少素数才能去除 99%99\%99% 的合数!这个模数又会是多么巨大!

假设整数 nnn 超过 252525 位,那么除以小于其平方根的轮式分解素数是不切实际的。如果 nnn 有 200200200 位,那么试除法是不可行的——所以需要更快的素性检验。我们将在下面讨论几个这样的检验。


二、费马数,概率素数和伪素数

费马大定理,也是他的“最后”定理,说明了当 n≥2n\geq 2n≥2 时,丢番图方程 xn+yn=znx^n + y^n = z^nxn+yn=zn 无正整数 x,y,zx, y, zx,y,z 解。 这最终被 Wiles 于 1995 年证明。此处我们关注的是他的“小”定理:

费马小定理 \;若 ppp 是素数,aaa 是任一整数,则 ap≡a(modp)a^p\equiv a \;(mod \;p)ap≡a(modp) ;特别地,若 p∤ap\nmid ap∤a ,则 ap−1≡1(modp)a^{p-1}\equiv 1 \;(mod \;p)ap−1≡1(modp) 。

费马小定理给了我们一个强大的合数性检验:给定 n>1n >1n>1、选择 a>1a>1a>1 ,并计算 an−1a^{n-1}an−1 模 nnn ( 有一种非常简单的方法叫快速幂二进制幂 ( binary exponentiation ) ,通过重复平方来快速完成 ) 。如果结果不是模 nnn 余 111 ,那么 nnn 是合数。如果是模 nnn 余 111 ,那么 nnn 可能是素数,所以 nnn 被称为基于 aaa 的弱概率素数 ( 或 a-PRP ) 。

一些早期文献把满足这个检验的所有数都称为伪素数,但是现在伪素数这个术语被适当地保留给合数概率素数

伪素数 ( 合数 PRPs ) 的最小示例如下。

  • 341=11⋅31341 = 11\cdot 31341=11⋅31 是一个 2-PRP, (Sarrus 1819) ,
  • 91=7⋅1391 = 7\cdot 1391=7⋅13 是一个 3-PRP ,
  • 217=7⋅31217 = 7\cdot 31217=7⋅31 是一个 5-PRP ,
  • 25=5⋅525 = 5\cdot 525=5⋅5 是一个 7-PRP .

虽然有 1,091,987,4051,091,987,4051,091,987,405 个素数小于 25,000,000,00025,000,000,00025,000,000,000 ,但其中只有 21,85321,85321,853 个以 222 为基数的伪素数,所以 Henri Cohen 开玩笑说 2-PRP 是工业级素数。幸运的是,nnn 越大,PRP 检验正确的可能性 ( 平均而言 ) 就越大——请参阅下图。

有趣的是,早在 1950 年,Lehmer 使用概率 / 伪素数的较弱定义 an≡a(modn)a^n≡a\; (mod \;n)an≡a(modn),发现 2⋅73⋅1103=1610382\cdot 73\cdot 1103 = 1610382⋅73⋅1103=161038 是一个以 222 为基底的偶伪素数。理查德·平奇在他的网站上列出了直到 102110^{21}1021 ( 根据各种定义 ) 的伪素数

伪素数可能相对较少,但对于每一个基数 a>1a>1a>1 ,伪素数仍然有无穷多,所以我们需要一个更严格的测试。使测试更准确的一种方法是使用多个基底 ( 检查以 222 为基底,然后以 333 为基底,然后以 555 为基底,… ),但我们仍然遇到了一个有趣的障碍,叫做卡迈克尔数 ( Carmichael numbers ) 。

定义 \;合数 nnn 是一个卡迈克尔数,如果 an−1≡1(modn)a^{n-1}\equiv 1 \;(mod \; n)an−1≡1(modn) 对任意与 nnn 互素的 aaa 都成立。

这里有一个坏消息:对一个卡迈克尔数的反复 PRPPRPPRP 检验将无法表明它是合数,直到我们找到它的一个因子。虽然卡迈克尔数罕见的 ( 只有 216321632163 个小于 25,000,000,00025,000,000,00025,000,000,000 ),但最近已经证明存在无限多个 [There are infinitely many Carmichael numbers, 1994] 。卡迈克尔数小于 101010 万的部分如下 ( 共 161616 个 ):

561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841, 29341, 41041, 46657, 52633, 62745, 63973, 75361.

理查德·平奇将卡迈克尔数列到了 101610^{16}1016 。

备注:Jon Grantham 提出了 Frobenius 伪素数的想法,以推广许多标准类型 ( Fermat, Lucas… ),并使检验更准确。他的论文可以在网上找到。


三、强概率素性检验

使费马检验更准确的一个更好的方法是:如果奇数 nnn 是素数,那么数字 111 只有两个平方根 111 和 −1-1−1 模 nnn 。所以 a(n−1)/2a(n-1)/2a(n−1)/2 ( 因为 nnn 是奇数 ) 模 nnn 等于 111 或 −1-1−1 。( 实际上可以用雅可比符号来计算它应该是哪个,但我们希望在这里开发一个更强大的检验 ) 。 如果 (n−1)/2(n-1)/2(n−1)/2 是偶数,我们可以很容易地再取一个平方根 …… 让我们把它变成一个算法:

记 n−1=2s⋅dn-1=2^s\cdot dn−1=2s⋅d ,其中 ddd 是奇数且 sss 非负:nnn 是一个基于 aaa 的强概率素数 ( a-SPRP ),如果对于某些非负数 r≤sr\leq sr≤s 有 ad≡1(modn)a^d \equiv 1 \;(mod \;n)ad≡1(modn) 或者 (ad)2r≡−1(modn)(a^{d})^{2^r} \equiv -1 \;(mod \;n)(ad)2r≡−1(modn) 这两者之一成立。

同样,所有整数 n>1n>1n>1 若未通过此检验的,为合数;通过检验的是概率素数。最小的奇合数 SPRP 如下:

  • 2047=23⋅892047 = 23\cdot 892047=23⋅89 是一个 2-SPRP,
  • 121=11⋅11121 = 11\cdot 11121=11⋅11 是一个 3-SPRP,
  • 781=11⋅71781 = 11\cdot 71781=11⋅71 是一个 5-SPRP,
  • 25=5⋅525 = 5\cdot 525=5⋅5 是一个 7-SPRP.

基于这些结果的检验非常快,特别是结合前几个素数使用的试除法。如果你在编写这些程序时遇到困难,Riesel [Prime numbers and computer methods for factorization, p100] 有用于 SPRP 测试的 PASCAL 代码,Bressoud 有伪代码[Factorizations and primality testing, p77], Langlois 提供 C 语言代码。

单独来说,这些测试仍然很弱 ( 每个基数 a>1a>1a>1 都有无穷多个合数 a-SPRP ),但我们可以将这些单独的检验结合起来,对小整数 nnn 进行更强大的检验:

  • 如果 n<1,373,653n<1,373,653n<1,373,653 既是 2-SPRP 也是 3-SPRP,那么 nnn 是素数,
  • 如果 n<25,326,001n<25,326,001n<25,326,001 既是 2-SPRP、3-SPRP 也是 5-SPRP,那么 nnn 是素数,
  • 如果 n<118,670,087,467n<118,670,087,467n<118,670,087,467 既是 2-SPRP、3-SPRP、5-SPRP 也是 7-SPRP,则要么 n=3,215,031,751n = 3,215,031,751n=3,215,031,751 ,要么 nnn 是素数,
  • 如果 n<2,152,302,898,747n<2,152,302,898,747n<2,152,302,898,747 既是 2-SPRP、3-SPRP、5-SPRP、7-SPRP 也是 11-SPRP,那么 nnn 是素数,
  • 如果 n<3,474,749,660,383n<3,474,749,660,383n<3,474,749,660,383 既是 2-SPRP、3-SPRP、5-SPRP、7-SPRP、11-SPRP 也是 13-SPRP,那么 nnn 是素数,
  • 如果 n<341,550,071,728,321n< 341,550,071,728,321n<341,550,071,728,321 既是 2-SPRP、3-SPRP、5-SPRP、7-SPRP、11-SPRP、13-SPRP 也是 17-SPRP,那么 nnn 是素数。

要根据这些结果快速进行素性检验,首先除以前几个素数 ( 比如低于 257257257 的素数 ),然后执行以 2,3,⋯2,3,\cdots2,3,⋯ 为基数的强素性检验直到满足上述条件之一。例如,如果 n<25,326,001n <25,326,001n<25,326,001 ,我们只需要检查基数 2,32,32,3 和 555 。这比试除法快得多,因为别人已经做了很多工作,但只适用于很小的数字 ( n<1016n<10^{16}n<1016 ) 。

请注意,可以通过不将它们作为单独的检验来加强这些结果,而是意识到我们正在寻找 −1-1−1 的平方根。例如,n=46,856,248,255,981n = 46,856,248,255,981n=46,856,248,255,981 是 222-伪素数 和 777-伪素数,但是
2(n−1)/4≡34456063004337(modn),2^{(n-1)/4} ≡ 34456063004337 \;(mod \;n) ,2(n−1)/4≡34456063004337(modn), 7(n−1)/4≡21307242304265(modn).7^{(n-1)/4} ≡ 21307242304265 \;(mod \;n).7(n−1)/4≡21307242304265(modn). 以上这两个的平方是 −1-1−1 。如果 nnn 是素数,那么它就只有两个平方根,并且上面的数是相等的或者是相反的 ( 显然两者皆不满足 ) 。然而 gcd⁡(n,34456063004337−21307242304265)=4840261\gcd(n, 34456063004337-21307242304265) = 4840261gcd(n,34456063004337−21307242304265)=4840261,我们便已经分解了 nnn 。

最后,还有很多可以 ( 也应该 ) 说的。我们可以讨论欧拉伪素数及其与 SPRP 的关系。或者我们可以换一下:讨论卢卡斯伪素数,或斐波那契伪素数,或重要的组合检验 …… 但这需要一本书的一章——而 Ribenboim [The new book of prime number records, 1995] 的书已经写得很好了。让我们以最后一个结果来结束本节:

米勒检验 ( Miller’s Test ):如果广义黎曼假设成立,那么当 nnn 是所有整数 a 的 a-SPRP ( 其中 1<a<2(log⁡(n))21<a<2(\log(n))^21<a<2(log(n))2 ) ,则 nnn 是素数。

广义黎曼假设对我们来说太复杂了,无法在这里解释——但如果它被证明了,那么我们就有了一个非常简单的素性检验。在它被证明之前,我们至少可以期望,如果 nnn 是合数,我们应该能够找到一个表明它是合数的 a ( 一个见证者 ),而不用搜索太长时间

大多数研究涵盖了米勒检验 ( 通常使用常数 a=707070,来自文献 [Oesterlé, Versions effectives du théorème de chebotarev sous l’hypothèse de riemann généralisée, 1979],正如米勒的文章所说的 O((logn)2)O((log n)^2)O((logn)2) ) 。可改进常数 a=222 是由 Bach 在文章 [Analytic methods in the analysis and design of number-theoretic algorithms, 1985] 中提出的。请注意,启发式地 Bach 和Huelsbergen [Statistical evidence for small generating sets, 1993] 认为我们应该能够用更小的边界替换 Miller 检验中的边界:
(log⁡2)−1log⁡nlog⁡log⁡n.(\log 2)^{-1} \log n \log \log n.(log2)−1lognloglogn. 请注意,在米勒检验中没有有限的基数集合。事实上,如果 nnn 是合数,我们让 W(n)W(n)W(n) 表示 nnn 的最小见证者 ( 最小 aaa 表明 nnn 是合数 ),那么有无穷多的合数 nnn 满足:
W(n)>(log⁡n)1/(3log⁡log⁡log⁡n)W(n) > (\log n)^{1/(3 \log \log \log n)}W(n)>(logn)1/(3logloglogn) 上述结论参见 [There are infinitely many Carmichael numbers, 1994] 。

译者补充米勒检验已经改进为目前常见的 Miller-Rabin 检验,不再依赖广义黎曼假设,该检验详细参考此处。

如何找到与证明素数之一:小素数和概率素数的快速检验相关推荐

  1. MATLAB 找到n阶方阵中对角线上的连续素数个数 不使用循环

    找到n阶方阵中对角线上的连续素数个数 n=input('请输入矩阵阶n'); A=fix(1000*rand(n)); %计算对角线上的连续素数个数 % 不使用循环,结果存入y B=diag(A)' ...

  2. 1亿以内素数的个数_神奇的素数

    数学里面最有趣的问题可能就得说是素数了.世界上最难的问题很多都与素数有关,而且素数又是如此简单的一个概念,只要是学过乘除法的人都能理解什么是素数.如果评选一个非常简单但又极端复杂的数学概念,估计非素数 ...

  3. python中编写函数素数_如何用Python编写素数程序?

    成为一个认证的专业素数是一个大于1的自然数,它没有除1以外的任何除数.你可以用Python编写一个代码来帮助你找到所有的素数.在本文中,我们将按照以下顺序在Python中编写一个素数程序:什么是素数? ...

  4. 输入一个正整数求所有素数因子_一起来聊聊素数的两个性质

    素数(prime number),又称质数,有无限个. 定义:在大于1的自然数中,除了1和它本身以外不再有其他因数. 来介绍两个简单的性质: 质数的个数是无穷的. 欧几里得的<几何原本>曾 ...

  5. 【小组专题四点五:素数】素数的分布,素数定理,素数猜想与兰道问题

    3.2 素数的分布与猜想 π(x)\pi(x)π(x) 的近似估计函数 1798年,法国数学家勒让德通过 JurijVegaJurij\;\;VegaJurijVega 计算到400031的素数表 得 ...

  6. java 素数 五行_【数论】素数的判定与筛法

    素数的判定与筛法 判定:很简单嘛!暴力大法参上! #include #include unsigned long int n,i,j,a,b; using namespace std; int mai ...

  7. java生成大素数_用BigInteger实现大素数生成算法

    一.通过素数的基本性质 根据素数的性质(除了1和此整数(n)自身外,无法被其他自然数整除的数):即从2到n/2的数都不能整除n. 1 public static booleanisPrime(BigI ...

  8. matlab 素数积,素数之美1:所有素数之积

    在之前的欧拉数学中,我们计算过所有素数的倒数之和,得出素数的倒数之和是发散的,从而这也是一个关于素数个数为无穷的证明.在本篇文章中,我们尝试计算所有素数之积,通过一个简单的技巧,得到素数之积的一个上限 ...

  9. java中判断 101-200 之间有多少个素数,并输出所有的素数

    题目:判断 101-200 之间有多少个素数,并输出所有的素数 素数是什么: 质数又称素数.一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数:否则称为合数. 那么题目的答案如下: ...

最新文章

  1. git命令从入门到实战,看这一篇足矣
  2. 信息系统项目管理师案例考试汇总(2005~2021年)
  3. RxLifecycle详细解析
  4. error: expected unqualified-id before 'public'
  5. 一个STM32编译Makefile模板
  6. InterlockedIncrement
  7. 如何在 Mac 上修复丢失的鼠标光标?
  8. github创建仓库,往github上上传自己的项目
  9. 八卦图代码matlab,12行javascript代码绘制一个八卦图_javascript技巧
  10. Qt 之播放m3u8视频流
  11. HTML代码 网页设置 QQ空间等分享
  12. Linux文件与目录常用操作
  13. 固态硬盘是什么接口_ssd固态硬盘是什么意思,有什么好处,固态硬盘和机械硬盘的区别...
  14. windows下AV1的编译
  15. 软考中级软件设计师--下午题
  16. java数组标准差_如何使用JAVA计算标准差
  17. 科学计算机怎么算锥度,如何计算锥度值?比如说1:20等于多少度?请说说具体步骤!-锥度的计算公式-数学-贾儆刹同学...
  18. win10计算机怎么注销用户,windows10系统如何取消微软账户登陆
  19. 嵌入式之linux用户空间与内核空间,进程上下文与中断上下文
  20. c语言把结构体首地址放入指针,C语言基础———指针,结构体指针,函数指针

热门文章

  1. bzoj3307: 雨天的尾巴
  2. 2022电大国家开放大学网上形考任务-会计学概论非免费(非答案)
  3. 明翰Java教学系列之认识Java篇V1.3(持续更新)
  4. Visio画图字体字号太小,默认8,如何设置默认更大字号
  5. 【六祎 - Java】对象序列化
  6. 大学计算机基础试题第六章,大学计算机基础第六章作业答案
  7. A律折线与miu律折线
  8. 【TED】How to get better at the things you care about?
  9. 智慧城市水质在线蓝绿藻监测传感器
  10. 图钉—将REST API转变为实时API的开源库