程序的结构和解释因此定义了费马小定理:
如果n是素数,并且a是小于n的任何正整数,则 升到n的幂等于模n。
(如果两个数字都具有 相同的余数除以n。 a除以n的余数 也称为模n的余数,或简称为模
基于该描述,我编写以下代码:
(define (fermat-test a n)
(congruent? (expt a n) a n))
(define (congruent? x y n)
(= (modulo x n)
(modulo y n)))
后来SICP这样说:
这将导致以下算法测试素数:给定一个 数n,选择一个随机数a
并给出以下代码:
(define (fermat-test)
(define (try-it)
(= (expmod a n n) a))
(try-it (+ 1 (random (- n 1)))))
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(remainder (expmod base (/ exp 2) m) m))
(else
(remainder (* base (expmod base (- exp 1) m)) m))))
其中expmod
是“一个计算以另一个数为模的数字的指数的过程”。
我不理解这段代码与费马定理的第一个定义之间的对应关系。我知道“加到n的幂等于模n”是:a^n modulo n = a modulo n
。但是SICP的代码似乎暗示a^n modulo n = a
。 fermat-test
过程中的条件不包括a modulo n
。当然,它们的实现有效,所以我一定会误会。
请注意,这并不是对递归与迭代过程的混淆。
答案 0 :(得分:2)
测试中的条件具有a
而不是a modulo n
,因为如果a < n
则a modulo n
是 a
,因此modulo n
是多余的。
他们真正测试的是n
是Fermat pseudoprime。它不能作为对素数的全面测试(并且SICP并不声称可以这样做),但是该测试中涉及的思想最终导致了完全实用的Miller-Rabin test。
答案 1 :(得分:0)
(exp n a)将计算非常大的数字
(expmod a n n)将计算一个介于0到n之间的数字
这两个值将是一致的(模n)。
使用expmod的原因是通过使用它可以使fermat-test更快。 fermat-test函数将以两种方式给出相同的结果。