Scheme SICP练习1.28-米勒·拉宾;至少有一半的数字将显示一个非平凡的平方根,即1的模n“;

Scheme 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

SICP练习1.28

费马测试的一个变体是不能被愚弄的 被称为米勒-拉宾试验(米勒1976;拉宾1980)。这就开始了 从Fermat小定理的另一种形式来看 如果n是素数,a是小于n的正整数,那么 升到(n-1)次方的a与模n的1全等。检验 一个数n的素性通过Miller-Rabin检验,我们选择一个随机数 编号a如果n是不是素数的奇数,那么, 对于至少一半的数字a(这就是 Miller-Rabin试验不能被愚弄。)将expmod程序修改为 如果发现非平凡的平方根为1,则发出信号,并使用该信号 采用类似以下步骤执行Miller-Rabin试验: 费马试验。通过测试各种已知的素数和 非素数。提示:制作expmod信号的一个方便方法是 它返回0

我已经编写了自己的解决方案,其结果与此处提供的解决方案一致:

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是素数,aa^(n-1)=1(模n)
为了通过Miller-Rabin检验检验一个数n的素性,我们选取一个随机数a 所以随机选取一个,检查a^(n-1)=1(mod n)。如果它不是,那么你知道n不是素数

然而,每当我们在expmod中执行平方步骤时,我们都会检查是否发现了一个“1模n的非平凡平方根”,即一个不等于1或n-1的数,其平方等于1模n

这是关于在expmod函数中添加一个额外的检查。这可能是你忽略的事情

可以证明,如果1的非平凡平方根存在,那么n不是素数

让我们详细讨论一下这个问题。1的非平凡平方根是一个数字x,因此x^2=1(mod n)。x不是1或-1

为什么其中一个表示n不是素数

我们知道x^2-1=(x-1)(x+1)和(工作模n)x-1和x+1都不是零,但它们的乘积是零。这意味着我们有一个复合模量,你可以通过取这两个值的GCD将其因子化

还可以证明,如果n是不是素数的奇数,那么,对于至少一半的数a 这又是关于向expmod函数的平方分支添加内部测试

修改expmod过程,以在发现非平凡平方根为1时发出信号,并使用类似于fermat测试的过程来实现Miller-Rabin测试。通过测试各种已知素数和非素数来检查您的程序。提示:使expmod信号返回0是一种方便的方法


希望有帮助!询问您是否需要更多指导。

我找到了一篇文章,其中介绍了该测试,并证明了一个具体结果,即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)