計算機プログラムの構造と解釈 第二版 P29 問題1.27
ここで出ている、charmichael数っていうのは、
561、1105、1729、2465、2821
っていう数で、
Felmatテストはパスするけど、素数ではない数。
教科書に書いてあった
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 ≡ b (modulo n), a ≡ b (mod n) あるいは a ≡n b などと表す。このように、合同関係をあらわす演算子で結ばれた式を合同式と総称する。a ≡ b (mod n) は、a, b それぞれを自然数 n で割ったときの剰余が等しいことと同値である。また同じことだが、整数 k の n を法とする剰余はしばしば k mod n で表されるので、この記法に従えば、合同式 a ≡ b (mod n) は等式 a mod n = b mod n に書き直すことができる(この等式で k mod n を後述のように剰余類の意味にとっても同じことである)。
整数の合同式
http://homepage3.nifty.com/sugaku/mod.htm
2数 a, b が pを法として合同
⇔
a-b がpで割り切れる。つまり整数kを用いて、a-b=pkとかける。
(あるいは、pで割った余りが等しい)これを a≡b (mod p)で表す。
なので、教科書にある
整数nをとり、a < n なるすべてのaでa^nがnを法として合同になるかどうか見る手続きを書き、
っつーのは、
(あるいは、pで割った余りが等しい)
って書いてある通りに考えて
aを、n-1から始めてを1ずつ引いていって1になるまで、
(イテレータ的?には、aを1から1ずつたしていって、n-1まで)
((a)^n) % n = a % n
が成り立てばいいということだ。
(まー a < n の関係から、a % n = a だけど、定義だしここのコードには残しておく)
なりたっていれば、素数である確率が高い。
そうでなければ、素数ではない。
なので、素数でないかどうか1-21で使った関数を使ってチェックしてからfelmatテストを行ってみる。
1 #!/usr/local/bin/gosh 2 ;; -*- coding: utf-8 -*- 3 4 5 ;;;1-21;;;;;;;;;;;;;;;;;;;;;;;;; 6 (define (square n) 7 (* n n)) 8 9 10 (define (smallest-divisor n) 11 (find-divisor n 2)) 12 13 (define (find-divisor n test-divisor) 14 (cond ((> (square test-divisor) n) n) 15 ((divides? test-divisor n) test-divisor) 16 (else (find-divisor n (cond ((= test-divisor 2) 3 ) 17 (else (+ test-divisor 2))))))) 18 19 (define (divides? a b) 20 (= (remainder b a) 0)) 21 22 (define (prime? n) 23 (cond ((= n (smallest-divisor n)) #t) 24 (else #f))) 25 ;;;;;;;;;;;;;;;;;;;; 26 27 ;;expmod実装 28 (define (expmod base exp m) ; a n n 29 (cond ((= exp 0) 1) 30 ((even? exp) 31 (remainder (square (expmod base (/ exp 2) m)) 32 m)) 33 (else 34 (remainder (* base (expmod base (- exp 1) m)) 35 m)))) 36 37 (define (test_for_charmichael_i a n) 38 (cond ((= a n) #t) 39 ((= (expmod a n n) (remainder a n)) (test_for_charmichael_i (+ a 1) n)) 40 (else #f))) 41 42 (define (test_for_charmichael? n) 43 (test_for_charmichael_i 1 n)) 44 45 46 (define (main args) 47 (display "charmichaelナンバーが、素数かチェック、素数なら#t")(newline) 48 (display "561:") 49 (display (prime? 561))(newline) 50 (display "1105:") 51 (display (prime? 1105))(newline) 52 (display "1729:") 53 (display (prime? 1729))(newline) 54 (display "2465:") 55 (display (prime? 2465))(newline) 56 (display "2821:") 57 (display (prime? 2821))(newline) 58 59 60 (newline) 61 (display "felmatテストを行う。素数性が確認されれば#t")(newline) 62 (display "561:")(print (test_for_charmichael? 561)) 63 (display "1105:")(print (test_for_charmichael? 1105)) 64 (display "1729:")(print (test_for_charmichael? 1729)) 65 (display "2465:")(print (test_for_charmichael? 2465)) 66 (display "2821:")(print (test_for_charmichael? 2821)) 67 0)
どうかな?
思惑通り、charmichael数は素数ではないが、素数性のテストはパスしている。