Scheme SICP练习1.28-米勒·拉宾;至少有一半的数字将显示一个非平凡的平方根,即1的模n“;
SICP练习1.28 费马测试的一个变体是不能被愚弄的 被称为米勒-拉宾试验(米勒1976;拉宾1980)。这就开始了 从Fermat小定理的另一种形式来看 如果n是素数,a是小于n的正整数,那么 升到(n-1)次方的a与模n的1全等。检验 一个数n的素性通过Miller-Rabin检验,我们选择一个随机数 编号aScheme SICP练习1.28-米勒·拉宾;至少有一半的数字将显示一个非平凡的平方根,即1的模n“;,scheme,primes,sicp,primality-test,Scheme,Primes,Sicp,Primality Test,SICP练习1.28 费马测试的一个变体是不能被愚弄的 被称为米勒-拉宾试验(米勒1976;拉宾1980)。这就开始了 从Fermat小定理的另一种形式来看 如果n是素数,a是小于n的正整数,那么 升到(n-1)次方的a与模n的1全等。检验 一个数n的素性通过Miller-Rabin检验,我们选择一个随机数 编号a
15
是一个非素数的奇数,因此对于从1
到14
的a
至少有一半的数字,我希望计算expmod(a,14,15)
将显示一个非平凡的1模n的平方根,它由expmod
返回0
表示
然而,我得到的结果如下:
(expmod 1 14 15)
> 1
(expmod 2 14 15)
> 4
(expmod 3 14 15)
> 9
(expmod 4 14 15)
> 0
(expmod 5 14 15)
> 10
(expmod 6 14 15)
> 6
(expmod 7 14 15)
> 4
(expmod 8 14 15)
> 4
(expmod 9 14 15)
> 6
(expmod 10 14 15)
> 10
(expmod 11 14 15)
> 0
(expmod 12 14 15)
> 9
(expmod 13 14 15)
> 4
(expmod 14 14 15)
> 1
可以看出,这些结果中只有2个是0
,比预期的至少7个差得多
我是不是误解了这个说法?我是个十足的白痴吗?代码错了吗?SICP错了吗?非常感谢
编辑1:要求我提供我正在使用的确切代码。在这里,虽然我基本上只是复制我链接到的解决方案,并将余数
别名为mod
,因为我的解释器就是这么叫它的
(define (square x) (* x x))
(define remainder mod)
(define (miller-rabin-expmod base exp m)
(define (squaremod-with-check x)
(define (check-nontrivial-sqrt1 x square)
(if (and (= square 1)
(not (= x 1))
(not (= x (- m 1))))
0
square))
(check-nontrivial-sqrt1 x (remainder (square x) m)))
(cond ((= exp 0) 1)
((even? exp) (squaremod-with-check
(miller-rabin-expmod base (/ exp 2) m)))
(else
(remainder (* base (miller-rabin-expmod base (- exp 1) m))
m))))
(define expmod miller-rabin-expmod)
(print (expmod 1 14 15))
(print (expmod 2 14 15))
(print (expmod 3 14 15))
(print (expmod 4 14 15))
(print (expmod 5 14 15))
(print (expmod 6 14 15))
(print (expmod 7 14 15))
(print (expmod 8 14 15))
(print (expmod 9 14 15))
(print (expmod 10 14 15))
(print (expmod 11 14 15))
(print (expmod 12 14 15))
(print (expmod 13 14 15))
(print (expmod 14 14 15))
编辑2:我现在还手动计算了expmod(a,14,15)
(总是通过exp=14
,exp=7
,exp=6
,exp=3
,exp=2
,exp=1
,exp=0
)的步骤,用于a
从1到14的所有值,我确信只有a=4
和a=11
遇到了非平凡的平方根1。所以我倾向于认为SICP在这一点上要么是错误的,要么是没有表达清楚
费马测试的一个变体是米勒-拉宾测试(Miller 1976;拉宾1980),它不能被愚弄。这是从Fermat小定理的另一种形式开始的,该定理指出,如果n是素数且a是小于n的任何正整数,则提升到(n-1)次方的a与模n的1全等
- n是素数,a
a^(n-1)=1(模n)
希望有帮助!询问您是否需要更多指导。我找到了一篇文章,其中介绍了该测试,并证明了一个具体结果,即2和n-2之间的值有一半以上会导致非平凡的平方根为1。(定理4.1)
(define (print x) (display x) (newline))
(define (assert p) (unless p (error 'assert-failed)))
(define (power-of-two-split m)
;; write m = 2^e k
(let loop ((e 0) (k m))
(if (even? k)
(loop (+ e 1) (quotient k 2))
(cons e k))))
(define (exp/mod a k n)
;; a^k (mod n)
(cond ((= k 0) 1)
((= k 1) (modulo a n))
(else (modulo (* a (exp/mod a (- k 1) n)) n))))
(define (miller-rabin a n)
(assert (odd? n))
(assert (= 3 (modulo n 4))) ;; only handles e=1 case, need to use power-of-two-split for full test
(let ((k (quotient (- n 1) 2)))
(exp/mod a k n)))
(define (test n)
(for ((i (in-range 2 (- n 2))))
(let ((m (miller-rabin i n)))
(print `(,i -> ,m squared ,(exp/mod m 2 n))))))
(test 15)
它将打印以下结果
(2 -> 8 squared 4)
(3 -> 12 squared 9)
(4 -> 4 squared 1)
(5 -> 5 squared 10)
(6 -> 6 squared 6)
(7 -> 13 squared 4)
(8 -> 2 squared 4)
(9 -> 9 squared 6)
(10 -> 10 squared 10)
(11 -> 11 squared 1)
(12 -> 3 squared 9)
因此,对照米勒·拉宾证人的正式定义,他们实际上都是温特丝:
定义2.3。对于奇数n>1,写入n− 1=2^ek,带k奇数,并选择a∈ {1,…,n− 1}. 我们说a是n的米勒-拉宾证人
(2 -> 4)
(3 -> 9)
(4 -> 1)
(5 -> 10)
(6 -> 6)
(7 -> 4)
(8 -> 4)
(9 -> 6)
(10 -> 10)
(11 -> 1)
(12 -> 9)