素數檢測雜談

最初咱們學到的是這種樸素的寫法:算法

(define (prime? n)
  (cond
   [(or (= n 2) (= n 3)) #t]
   [(even? n) #f]
   [else (prime-test-loop n)]))

(define (prime-test-loop n)
  (let ((top (ceiling (sqrt n))))
    (let iter ((start 3))
      (cond [(> start top) #t]
            [(= (mod n start) 0) #f]
            [else (iter (+ start 2))]))))

雖然很笨拙,但其實這也是通過「優化」的,首先,除了 2 之外的偶數就不用判斷了。其次,試除迭代從 3 起步,每次 +2,一樣避開了偶數。最後,循環的結束條件是 (sqrt n).數組

後來又看到一種生成素數序列的方法,大致思想是維護一個已知的素數表,每個新的數字 n 都用已知素數表裏的數去試除。若是都不能整除,說明 n 是素數,將 n 添加到已知的素數表裏,進入下一輪迭代。原文是用 C 實現的,事先搞一個大數組,每一輪迭代都遍歷數組,將已知素數的整數倍所對應的數組下標都劃掉,最後留在數組中的就是素數。其實這個算法也是 O(N^2) 複雜度,隨着 n 的增加,其代價也將迅速地變得不可接受。下面是我寫的 Scheme 版:dom

(define (prime-list n)
  (let iter ((start 3) (primes '(2)))
    (cond [(> start n) primes]
          [(andmap (lambda (p) (not (= (mod start p) 0)))
                   primes)
           (iter (+ start 2) (cons start primes))]
          [else (iter (+ start 2) primes)])))

後來知道有一種基於機率的檢測方法叫費馬檢查,SICP 上就有一個實現,順便貢獻了一個 O(logN) 的快速乘方取模算法:函數

(define (square n) (* n n))

(define (expmod base exp m)
  (cond ((= exp 0) 1)
        ((even? exp)
         (mod (square (expmod base (/ exp 2) m))
              m))
        (else
         (mod (* base (expmod base (- exp 1) m))
              m))))

(define (fermat-test n)
  (define (try-it a)
    (= (expmod a n n) a))
  (try-it (+ 1 (random (- n 1)))))

(define (fast-prime? n times)
  (cond ((= times 0) #t)
        ((fermat-test n) (fast-prime? n (- times 1)))
        (else #f)))

這個算法不是很可靠,由於它所依據的理論是個僞命題,費馬小定理斷言:若是 n 是一個素數,那麼小於 n 的任意正整數 a 的 n 次方再對 n 取模,結果依然爲 a。oop

它的逆命題是,a 是任意一個小於 n 的正整數, 若是 a ^ n % n = a,那麼 n 就是一個素數。很遺憾,這個逆命題不成立,由於有一類數叫作 Carmichael 數,它符合 a ^ n % n = a 這個特性,但卻不是素數。直接用這段程序檢查一個數是否是素數有很大的機會出錯。這是已知 Carmichael 數的一部分:測試

561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841, 29341, 41041, 46657, 52633, 62745, 63973, 75361, 101101, 115921, 126217, 162401, 172081, 188461, 252601, 278545, 294409, 314821, 334153, 340561, 399001, 410041, 449065, 488881, 512461

能夠看到,最小的數是 561。若是你準備寫一個程序,生成一個素數表,然而它迭代了 500 屢次之後就開始胡言亂語,玩笑有點開大發了。 SICP 提到一個費馬檢測的變形,叫作 Miller-Rabin 檢測,它可以避免 Carmichael 數的愚弄。優化

這個檢測依據的斷言是:若是 n 是一個素數,a 是任意一個小於 n 的正整數,那麼 a ^ (n-1) % n = 1 % n翻譯

要用 米勒-拉賓 檢測算法測試一個數字是否是素數,咱們應當選擇一個小於 n 的隨機正整數 a, 而後利用 expmod 函數計算 a ^ (n-1) % n . 可是執行到 expmod 裏的 square 那一步時,咱們檢測是否是找到了一個 (1 % n) 的非平凡的平方根,換言之,看一看是否是有這樣一個數字,它既不是 1, 也不是 n-1,可是它的平方等於 1 % n。很容易證實,若是這樣一個 1 的非平凡的平方根存在,那麼 n 確定不是素數。一樣能夠證實,若是 n 是一個並不是素數的奇數,在小於 n 的正整數中,至少有一半在用這種方法計算 a ^ (n-1) 時可以找到這種非凡平方根。code

中文版的 SICP 看不太明白,我本身翻譯英文題目,仍是以爲看不太明白。但大概意思明白了,若是一個小於 n 的正整數 a,它符合 a ^ (n-1) & n = 1,可是 a 既不是 1, 也不是 n-1,那麼這個 n 確定不是素數。對一個僞素數來講,只作一次測試,正確與錯誤的機率對半分(事實上,出錯的機率遠遠小於一半),基本和算命差很少。若是作兩次測試,那就頗有可能發現它的真面目。重複的次數越多,結果越可信。若是重複屢次依然經過了測試,那個這個數 n 大概真的是個素數了。與費馬檢查不一樣,費馬檢查遇到 Carmichael 數不管重複多少次都沒法給出正確的結果的。這就是它能避免 Carmichael 數愚弄的緣由。ip

SICP 留了一個做業 1.28 ,要求實現 Miller-Rabin 檢測,下面是具體實現:

(define (expmod base exp m)
  (cond ((= exp 0) 1)
        ((even? exp)
         (check-nontrivial-sqrt (expmod base (/ exp 2) m) m)) ;; look here
        (else
         (mod (* base (expmod base (- exp 1) m)) m))))

(define (check-nontrivial-sqrt n m)
  (let ((x (mod (square n) m)))
    (if (and (not (= n 1))
             (not (= n (- m 1)))
             (= x 1))
        0
        x)))

(define (miller-rabin-test n)
  (define (try-it a)
    (= (expmod a (- n 1) n) 1))
  (try-it (+ 1 (random (- n 1)))))

(define (fast-prime? n times)
  (cond ((= times 0) #t)
        ((miller-rabin-test n) (fast-prime? n (- times 1)))
        (else #f)))

;; 搞了個包裝函數,偶數就沒必要判斷了吧
(define (prime? n)
  (cond ((= n 2) #t)
        ((even? n) #f)
        (else (fast-prime? n 10))))

上面的代碼我將迭代次數設爲10次,事實上我用5次迭代來測試全部已知的 Carmichael 數,重複了不少次都沒有發生錯誤。10次的迭代次數大概就能夠把錯誤機率降到宇宙射線引起 CPU 執行指令錯誤的程度了吧。下面是測試代碼和數表:

(define fname "Carmichael-list")

(call-with-input-file fname
  (lambda (ip)
    (let iter ((n (read ip)))
      (cond
       ((eof-object? n) #t)
       ((prime? n)
        (print n " test failed!" nl)
        (iter (read ip)))
       (else
        (iter (read ip)))))))

前方高能的分隔線


Carmichael-list:

561
1105
1729
2465
2821
6601
8911
10585
15841
29341
41041
46657
52633
62745
63973
75361
101101
115921
126217
162401
172081
188461
252601
278545
294409
314821
334153
340561
399001
410041
449065
488881
512461
530881
552721
656601
658801
670033
748657
825265
838201
852841
997633
1024651
1033669
1050985
1082809
1152271
1193221
1461241
1569457
1615681
1773289
1857241
1909001
2100901
2113921
2433601
2455921
2508013
2531845
2628073
2704801
3057601
3146221
3224065
3581761
3664585
3828001
4335241
4463641
4767841
4903921
4909177
5031181
5049001
5148001
5310721
5444489
5481451
5632705
5968873
6049681
6054985
6189121
6313681
6733693
6840001
6868261
7207201
7519441
7995169
8134561
8341201
8355841
8719309
8719921
8830801
8927101
9439201
9494101
9582145
9585541
9613297
9890881
10024561
10267951
10402561
10606681
10837321
10877581
11119105
11205601
11921001
11972017
12261061
12262321
12490201
12945745
13187665
13696033
13992265
14469841
14676481
14913991
15247621
15403285
15829633
15888313
16046641
16778881
17098369
17236801
17316001
17586361
17812081
18162001
18307381
18900973
19384289
19683001
20964961
21584305
22665505
23382529
25603201
26280073
26474581
26719701
26921089
26932081
27062101
27336673
27402481
28787185
29020321
29111881
31146661
31405501
31692805
32914441
33596641
34196401
34657141
34901461
35571601
35703361
36121345
36765901
37167361
37280881
37354465
37964809
38151361
38624041
38637361
39353665
40280065
40430401
40622401
40917241
41298985
41341321
41471521
42490801
43286881
43331401
43584481
43620409
44238481
45318561
45877861
45890209
46483633
47006785
48321001
49333201
50201089
53245921
54767881
55462177
56052361
58489201
60112885
60957361
62756641
64377991
64774081
65037817
65241793
67371265
67653433
67902031
67994641
68154001
69331969
70561921
72108421
72286501
74165065
75151441
75681541
75765313
76595761
77826001
78091201
78120001
79411201
79624621
80282161
80927821
81638401
81926461
82929001
83099521
83966401
84311569
84350561
84417985
87318001
88689601
90698401
92625121
93030145
93614521
93869665
94536001
96895441
99036001
99830641
99861985
100427041
101649241
101957401
102090781
104404861
104569501
104852881
105117481
105309289
105869401
107714881
109393201
109577161
111291181
114910489
115039081
115542505
116682721
118901521
119327041
120981601
121247281
122785741
124630273
127664461
128697361
129255841
129762001
130032865
130497361
132511681
133205761
133344793
133800661
134809921
134857801
135556345
136625941
139592101
139952671
140241361
144218341
145124785
146843929
150846961
151530401
151813201
153927961
157731841
158404141
158864833
159492061
161035057
161242705
161913961
163954561
167979421
168659569
169057801
169570801
170947105
171679561
172290241
172430401
172947529
173085121
174352641
175997185
176659201
178451857
178482151
178837201
180115489
181154701
182356993
184353001
186393481
186782401
188516329
188689501
189941761
193910977
194120389
194675041
196358977
200753281
206955841
208969201
212027401
214850881
214852609
216821881
221884001
226509361
227752993
228842209
230630401
230996949
231194965
237597361
238244041
238527745
241242001
242641153
246446929
247095361
250200721
252141121
255160621
256828321
257495641
258634741
266003101
270857521
271481329
271794601
273769921
274569601
275283401
277241401
278152381
279377281
280067761
288120421
289860481
291848401
292244833
292776121
295643089
295826581
296559361
299736181
300614161
301704985
302751505
306871201
311388337
321197185
321602401
328573477
329769721
333065305
333229141
338740417
334783585
346808881
348612265
354938221
357380101
358940737
360067201
362569201
364590721
366532321
366652201
367804801
367939585
368113411
382304161
382536001
390489121
392099401
393513121
393716701
395044651
395136505
399906001
403043257
405739681
413058601
413138881
416964241
419520241
426821473
429553345
434330401
434932961
438359041
440306461
455106601
458368201
461502097
461854261
462199681
471905281
471441001
473847121
477726145
481239361
483006889
484662529
490099681
490503601
492559141
503758801
507726901
510825601
511338241
516684961
517937581
518117041
518706721
527761081
529782121
530443201
532758241
540066241
542497201
544101481
545363281
547652161
548871961
549333121
549538081
551672221
552894301
555465601
556199281
556450777
557160241
558977761
561777121
564651361
568227241
569332177
573896881
577240273
579606301
580565233
590754385
595405201
597717121
600892993
602074585
602426161
606057985
609865201
612816751
616463809
620169409
625060801
625482001
629692801
631071001
633639097
652969351
656187001
662086041
683032801
683379841
686059921
689880801
697906561
702683101
703995733
704934361
710382401
710541481
711374401
713588401
717164449
727083001
739444021
743404663
744866305
752102401
759472561
765245881
771043201
775368901
775866001
776176261
784966297
790020001
790623289
794937601
798770161
804978721
809702401
809883361
814056001
822531841
824389441
829678141
833608321
834244501
839275921
841340521
843704401
847491361
849064321
851703301
851934601
852729121
855734401
863984881
867800701
876850801
882796321
885336481
888700681
897880321
902645857
914801665
918661501
928482241
931694401
934784929
935794081
939947009
940123801
941056273
954732853
955134181
957044881
958735681
958762729
958970545
962442001
962500561
963168193
968553181
975303121
977892241
981567505
981789337
985052881
990893569
993420289
993905641
1001152801
1027334881
1030401901
1031750401
1035608041
1038165961
1055384929
1070659201
1072570801
1093916341
1100674561
1103145121
1125038377
1131222841
1136739745
1177195201
1180398961
1189238401
1190790721
1193229577
1198650961
1200456577
1200778753
1207252621
1213619761
1216631521
1223475841
1227220801
1227280681
1232469001
1251295501
1251992281
1256855041
1257102001
1260332137
1264145401
1268604001
1269295201
1295577361
1299963601
1309440001
1312114945
1312332001
1316958721
1317828601
1318126321
1321983937
1332521065
1337805505
1348964401
1349671681
1376844481
1378483393
1382114881
1384157161
1394746081
1394942473
1404111241
1407548341
1422477001
1428966001
1439328001
1439492041
1441316269
1442761201
1490078305
1504651681
1507746241
1515785041
1520467201
1528936501
1540454761
1574601601
1576826161
1583582113
1588247851
1597821121
1626167341
1632785701
1646426881
1648076041
1659935761
1672719217
1676203201
1685266561
1688214529
1689411601
1690230241
1699279441
1701016801
1708549501
1726372441
1746692641
1750412161
1760460481
1772267281
1776450565
1778382541
1785507361
1795216501
1801558201
1803278401
1817067169
1825568641
1828377001
1831048561
1833328621
1841034961
1846817281
1848681121
1849811041
1879480513
1894344001
1899525601
1913016001
1918052065
1942608529
1943951041
1949646601
1950276565
1954174465
1955324449
1958102641
1976295241
1984089601
1988071801
2000436751
2023528501
2049293401
2064236401
2064373921
2067887557
2073560401
2080544005
2097317377
2101170097
2105594401
2107535221
2126689501
2140538401
2140699681
2301745249
2323147201
2436691321
2438403661
2444950561
2456536681
2529410281
2560600351
2598933481
2690867401
3264820001
3313196881
3480174001
3504570301
3713287801
3787491457
3835537861
4034969401
4215885697
4464573049
4562359201
4765950001
5255104513
5278692481
5781222721
5959748521
6047866621
6630702121
6916775113
7045248121
7629221377
8044161481
8251854001
8346731851
8652633601
8714965001
8976678481
9030158341
9086767201
9139810681
9293756581
9624742921
9701285761
9789244921
10119879001
10277275681
11346205609
12121569601
12173703001
12456671569
13079177569
13691148241
13946829751
14313548881
15906120889
16157879263
16765869121
17930792881
18151032901
18500666251
19742849041
21515221081
21796387201
22062297601
23224518901
23707055737
24285378001
25509692041
25749237001
26624905201
27278026129
30923424001
31876135201
34153717249
45983665729
48874811311
51436355851
51476019409
52756389001
57274147841
58094662081
59512667761
63593140801
64188507241
65700513721
67495942201
71171308081
82380774001
83946864769
100264053529
110296864801
168003672409
172018713961
173032371289
192739365541
225593397919
461574735553
464052305161
2199733160881
10028704049893
84154807001953
197531244744661
973694665856161
1436697831295441
1493812621027441
2094319836529921
2842648863161185
5778659093725441
6665161459969441
8015398984895401
8084842432668001
8188730132744161
12300849473799601
16166305446157945
32769125985828961
36629326277622001
39108343499765281
34795784213714161
37244219285276641
51116737346161201
61754693922936001
74538625278452401
91010482208190721
103183537035680641
126708084584398801
166857847951798081
186551892579535561
190232114399046721
194379756103868401
314610088213970641
335642734654849441
346413738355448401
556237362582392401
790689421836863641
1222628719906994401
1228155123631509217
1719756626091706801
2448237906710996401
2851896013395343201
3589102252820237401
4954039956700380001
相關文章
相關標籤/搜索