费马小定理在素数检测中的应用
因为还没用过liux的编译环境,我这两天便寻思着在Windows上搭建一个scheme的编译环境。查阅了各路大神的搭建方式,最终选择在VSC上进行编译,不过整了两天只能说勉强能用。只有编译功能,无法debug也没有调试,而且最奇怪的是只能在终端上进行运行,编译界面的主要作用只有关键词联想和补括号,可有可无。但是各路大神的教程内容里似乎都可以正常编译,我只在reddit上看到和我有同样疑问的一位朋友,最新的解答也是只能在终端界面进行编辑。不知道是否有相同疑问的朋友,我的水平有限,还烦请解答一下该问题。
言归正传,这次学习的内容关于素数检测,其中对费马小定理进行了应用(如果n是一个素数,a是小于n的任意正整数,那么a的n次方与a通模n同余),那么理论上只要使用足够多的a<n,就能比较有把握的判断一个数是否为素数,有点类似蒙特卡洛算法。为了实现费马检测,我们需要下列过程。
点击查看代码
; 一个数的幂对另一个数的取模过程
(define (expmod base exp m)
(cond ((= exp 0) 1 )
((even? exp)
(remainder (square (expmod base (/ exp 2) m)) m ))
(else
(remainder (* base (expmod base (- exp 1) m)) m ))))
; 定义平方,方便减少幂运算的步数
(define (square n)
(* n n))
; 判断偶数,作用同上一步
(define (even? n)
(= (remainder n 2) 0 ) )
; 费马检测过程,随机数a来源于1到n-1,这里通过random函数实现
(define (fermat-test n)
(define (try-it a)
(= (expmod a n n) a ))
(try-it (+ 1 (random (- n 1)))))
; 这里规定一定次数的检测,次数耗尽如果没找到反例则有较大把握确认目标为素数
(define (fast-prime? n times)
(cond ((= times 0) (display "true"))
((fermat-test n) (fast-prime? n (- times 1)))
(else (display "false"))))
相较于从2开始挨个试验是否能够整除的素数检测方式,费马检测在步数上的增长阶为log n,空间上几乎为1,因为取决于我们所规定检测数字数量。相较于传统的开方成长阶,有一定的资源优势。
后续的练习题中涉及到了runtime,通过编译过程的耗时来直观体现步数和空间的资源消耗。可惜当前的编译环境(见文章开头)不支持,故这部分习题无法很好解答。
习题1.28中增加了费马小定理的改进版,MR检查,是费马小定理的一个变型,其核心为:如果n是素数,对于任何小于n的整数a,则a的(n-1)次幂与1模n同余。但题目要求通过非平凡平方根的存在证明n是否为素数。
点击查看代码
(define (square n)
(* n n))
(define (even? n)
(= (remainder n 2) 0 ) )
(define (expmod base exp m)
(cond ((= exp 0) 1 )
((even? exp)
(com (expmod base (/ exp 2) m) m ))
(else
(remainder (* base (expmod base (- exp 1) m)) m ))
))
(define ( com x m )
(define (deal rem)
(if (= rem 1)
0
rem ))
(cond ((= x 1) 1)
((= x (- m 1)) (remainder (square x)m))
(else (deal (remainder (square x) m )))))
(define (MR-test n base)
(cond ((= base 1) 1)
((= (expmod base n (+ n 1)) 1 ) (MR-test n (- base 1)))
(else 0))
)
(define (fast-prime? n base)
(MR-test (- n 1) base))

浙公网安备 33010602011771号