math - 费马小定理与 SICP 实现有什么对应关系?
问题描述
程序的结构和解释这样定义了费马小定理:
如果 n 是素数并且 a 是小于 n 的任何正整数,则 a 的 n 次幂等于模 n。
(如果两个数在除以 n 时具有相同的余数,则称它们为模 n 一致。a 除以 n 时的余数也称为模 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 < n 并计算 a^n 模 n 的余数。如果结果不等于a,那么n肯定不是素数。
并给出以下代码:
(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
是“计算一个数模另一个数的指数的过程”。
我不明白这段代码和费马定理的第一个定义之间的对应关系。我将“a 的 n 次幂与模 n 一致”理解为:a^n modulo n = a modulo n
. 但 SICP 的代码似乎暗示a^n modulo n = a
. 程序中的条件fermat-test
不包括a modulo n
。当然,它们的实现是有效的,所以我一定是误解了。
请注意,这不是递归与迭代过程的混淆。
解决方案
测试中的条件 hasa
而不是a modulo n
因为 if a < n
then a modulo n
is a
,所以 themodulo n
是多余的。
他们真正测试的是是否n
是Fermat 伪素数。它不能作为一个完整的素数测试(SICP 也没有声称它确实如此),但测试中涉及的想法最终导致了完全实用的Miller-Rabin 测试。
推荐阅读
- javascript - 如何为反应组件添加优先级?
- html - 如何将数组映射到头像元素
- sql - 如何在 DB2 存储过程中使用 SET OPTION
- vim - 如何在 {string} 所在的位置用之前的 `*` 搜索的结果预填充替代命令?
- rest - 带有 NGINX 入口控制器的 REST URI
- javascript - 在javascript中,为什么下面的代码不退出循环?
- android - Glide:当第一个 URL 加载失败时尝试第二个 URL
- php - 将月份名称格式化为当地语言
- javascript - 如何使用赛普拉斯测试网页已禁用滚动?
- html - 无论屏幕大小如何,在元素上保持相对于其他元素的相同位置