Scheme 诡异

Scheme 诡异,scheme,Scheme,我试图在Scheme中实现Fermat的素性测试。 我编写了一个过程fermat2(最初称为fermat1),它返回true 当^p-1同余1(mod p)(请正确阅读!!) A. 每个素数p都应该满足这个过程(因此Fermat的小定理…) 对于任何一个 但是当我试图计算这个程序在固定次数的试验中产生的次数时。。。(使用COUNT程序,在代码中描述)我得到了令人震惊的结果 所以我稍微改变了这个过程(我看不到任何逻辑上的变化..可能是我瞎了)并将它命名为fermat1(取代旧的fermat1,现在

我试图在Scheme中实现Fermat的素性测试。 我编写了一个过程fermat2(最初称为fermat1),它返回true 当^p-1同余1(mod p)(请正确阅读!!) A. 每个素数p都应该满足这个过程(因此Fermat的小定理…) 对于任何一个 但是当我试图计算这个程序在固定次数的试验中产生的次数时。。。(使用COUNT程序,在代码中描述)我得到了令人震惊的结果 所以我稍微改变了这个过程(我看不到任何逻辑上的变化..可能是我瞎了)并将它命名为fermat1(取代旧的fermat1,现在是旧的fermat1->fermat2),它成功了。。素数总是通过测试

为什么fermat2程序调用的次数更少。。。到底怎么了?? 如果它是错误的,为什么我没有得到错误。。。相反,该计算被跳过!!(我想是的!)

你要做的就是理解我想说的

(countt fermat2 19 100)
(countt fermat1 19 100)
你自己看看

代码:

我真的很痛苦。。弄清楚它到底做了什么。。请按照代码说明为什么调用两次此DICRepiences?

偶数(countt fermat2 19 100)返回不同的结果

让我们修复你的
fermat2
,因为它比较短。定义是:“如果n是素数,a是小于n的任何正整数,则升到n次方的a与模n全等。”。这意味着
f(a,n)=a^n模n==a模n
。你的代码告诉你f(a,n)=a^(n-1)mod n==1,这是不同的。如果我们根据定义重写此项:

(define (fermat2 n)
  (define (tryout a x)
    (= (remainder (fast-exp a x) x) 
       (remainder a x)))

  (tryout (1+ (random n)) n))
这还不正确
(1+(随机n))
返回从1到n(包括1到n)的数字,而我们需要
[1..n)

这是正确的版本,但我们可以提高它的可读性。由于您仅在fermat2的范围内使用
tryout
,因此无需在参数
x
中传递
n
-后者已绑定在
tryout
的范围内,因此最终版本为

(define (fermat n)
  (define (tryout a)
    (= (remainder (fast-exp a n) n) 
       (remainder a n)))

  (tryout (+ 1 (random (- n 1)))))
更新:


我说过费马第二章中使用的公式是不正确的。这是错误的,因为如果
a*k=b*k(mod n)
那么
a=b(mod n)
。Vasu指出的错误是为测试生成随机数。

我同意……我知道这就是问题所在……但当您调用fermat2 n次时……调用试用的次数非常少(请取消对显示语句的注释)如果我的代码看起来像fortran ish或c语言,请原谅。我对scheme和声明性编程不熟悉。我完全理解fermat2的原因(我通过编写fermat1进行了更正,它是正确的..是的,绑定变量,词汇范围)是错误的。但是为什么试运行的次数比你评论显示语句的次数要少呢。我得到的是当我说(countt fermat1 19 100)得到时,我被呼叫了23次,19次(一些随机的次数和那些通过测试的次数)在上面的示例中,它被调用的次数少于100次,因为在某个时刻,
fermat2
返回
false
,因此触发了
cond
的第三个子句,该子句迄今为止返回
c
的值。
fermat2
问题中可能会返回质数的
false
,因为您对它使用了错误的公式(请参见我答案顶部的内容)。如果您尝试我答案中的最后一个片段作为Fermat测试,您将看到(countt Fermat 19 100)每次调用时都返回100。对,您的Fermat过程是正确的,我认为我的fermat1也是正确的(本例中它也给出100),但urs更整洁:)…这对我来说是愚蠢的…我没有计算一个过程通过的次数(真),而是计算它在失败之前通过的次数…毕竟没那么奇怪!!…谢谢hoha…(当一个副本粘贴以前过程的代码并且懒得修改它时会发生这种情况)你是对的-'fermat1'可以工作(我已经编辑了我的答案)。但它仍然有一个怪癖-它在选择要测试的数字时优先选择1(如果
random
返回1或0,则选择1)。我仍然推荐(+1(random(-n1))),因为它公平地选择数字。
(define (fermat2 n)
  (define (tryout a x)
    (= (remainder (fast-exp a x) x) 
       (remainder a x)))

  (tryout (+ 1 (random (- n 1))) n))
(define (fermat n)
  (define (tryout a)
    (= (remainder (fast-exp a n) n) 
       (remainder a n)))

  (tryout (+ 1 (random (- n 1)))))