計算機プログラムの構造と解釈 第二版 P29 問題1.28
[追記20090226]
これソースコードのところ、間違ってます。
教科書の以下のくだりに目をつけた。
つまり1でもn-1でもないがその二乗がnを法として1になる数がなかったか調べる。そういうnを法とした1の自明でない平方根があれば、nが素数でないことが証明できる
ぎりぎりわかりそうだ。
上記の転載部分の前半を考える。
つまり、ある数の二乗がnを法として1になればいい。
a^2 ≡ 1 (mod n)
a は 1 < a < n-1
のとき、nは素数でないということがわかった。
つまりだ、
wikipedia 合同式
http://ja.wikipedia.org/wiki/%E5%90%88%E5%90%8C%E5%BC%8F
二つの整数 a, b は、a − b が自然数 n で割り切れるとき、n を法として合同(n をほうとしてごうどう、congruent modulo n )であるといい、
ってかいてあるから、
(a^2 -1) % m
が0になるかどうか確かめればいい。
あとは、書いてあるとおりで、expmodでその数があったら、0を返すようにすれば何とかなる。
素数とか、Carmichael数とかでもテストしてみたけどたぶんいけてる。
もう、能率とか考えずに泥臭いコードを書いてみました。
と、書いてる間にミス発覚、変更点1にand条件がいくつか必要。
以下ソースコード。
1 #!/usr/local/bin/gosh 2 ;; -*- coding: utf-8 -*- 3 4 (use ggc.debug.trace) 5 (use math.mt-random) 6 7 ;;random;;;;;;;;;;;;;;;;;;;;;; 8 (define mt (make <mersenne-twister> :seed (sys-time))) 9 (define (random n) 10 (mt-random-integer mt n)) 11 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 12 13 14 (define (square n) 15 (* n n)) 16 17 18 19 (define (expmod base exp m) 20 (cond ((= exp 0) 1) 21 ;;ここ変更点1 22 ((= exp 2) 23 (cond ((= (remainder (- (square base) 1) m) 0) 0) 24 (else 25 (remainder (square (expmod base (/ exp 2) m)) 26 m)))) 27 ((even? exp) 28 (remainder (square (expmod base (/ exp 2) m)) 29 m)) 30 (else 31 (remainder (* base (expmod base (- exp 1) m)) 32 m)))) 33 34 (define (miller-rabin-test n) 35 (define (try-it a) 36 ;;ここ変更点2 37 (and (= (expmod a n n) a) (not(= (expmod a n n) 0)))) 38 (try-it (+ 1 (random (- n 1))))) 39 40 (define (fast-prime? n times) 41 (cond ((= times 0) #t) 42 ((miller-rabin-test n) (fast-prime? n (- times 1))) 43 (else #f))) 44 45 (define (prime? n) 46 (fast-prime? n 5)) 47 48 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 49 50 51 ;; main 52 (define (main args) 53 54 (display "cmiller-rabin-test 素数とすでに確認された数が素数かチェック")(newline) 55 (display "1009:")(print (prime? 1009)) 56 (display "1013:")(print (prime? 1013)) 57 (display "1019:")(print (prime? 1019)) 58 (display "10007:")(print (prime? 10007)) 59 (display "10009:")(print (prime? 10009)) 60 (display "10037:")(print (prime? 10037)) 61 (newline) 62 63 (display "偶数と素数でない奇数を素数かチェック")(newline) 64 (display "9:")(print (prime? 9)) 65 (display "20:")(print (prime? 20)) 66 (display "21:")(print (prime? 21)) 67 (display "49:")(print (prime? 49)) 68 (display "81:")(print (prime? 81)) 69 (display "100:")(print (prime? 100)) 70 (newline) 71 72 (display "cmiller-rabin-test charmichaelナンバーが、素数かチェック")(newline) 73 (display "テストを行う。素数性が確認されれば#t")(newline) 74 (display "561:")(print (prime? 561)) 75 (display "1105:")(print (prime? 1105)) 76 (display "1729:")(print (prime? 1729)) 77 (display "2465:")(print (prime? 2465)) 78 (display "2821:")(print (prime? 2821)) 79 80 (newline) 81 0)