计算机程序的构造和解释 练习题1.27

我们把1.22和1.24两个找素数的过程融合,变成找carmichael数的方法,也就是一个数通过所有的费马检查,但是不通过最小因数检查。以下是变更后的过程。

#lang racket

(define (square x) (* x x))
(define (runtime) ( current-inexact-milliseconds ))

(define(smallest-divisor n)
	(find-divisor n 2))
(define(find-divisor n test-divisor)
	(cond((>(square test-divisor) n ) n)
		((divides? test-divisor n) test-divisor)
		(else(find-divisor n (+ test-divisor 1)))))

(define(divides? a b)
	(=(remainder b a) 0))
(define (prime? n)
	(= n (smallest-divisor 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 (fermat-test n a)
    (= (expmod a n n) a))

(define (fast-prime? n times)
  (cond ((= times 0) #t)
        ((fermat-test n times) (fast-prime? n (- times 1)))
        (else #f)))


(define (timed-carmichael-test n) 
	(start-carmichael-test n (runtime)))
(define (start-carmichael-test n start-time)
	(if (and (fast-prime? n (- n 1)) (not (prime? n)))
		(begin (report-prime n (- (runtime) start-time)) #t) #f))
(define(report-prime n elapsed-time)
  	(newline)
        (display n)
	(display " usetime ")
	(display elapsed-time))
	
(define (search-for-carmichael n count)
  (cond((= count 0) n )
  ((timed-carmichael-test n) (search-for-carmichael (+ n 1) (- count 1)))
    (else (search-for-carmichael (+ n 1) count))))


(search-for-carmichael 500 10)

找出大于500的10个Carmichael数,跟书上面写的是一致的结果,不过为什么注释说10000000里面有255个这种数,计算机人对255天生敏感吧,这些数可能具备某些神奇的二进制数特质,暂时不做研究了。

561 usetime 0.975830078125
1105 usetime 0.976806640625
1729 usetime 1.952880859375
2465 usetime 4.88232421875
2821 usetime 9.763427734375
6601 usetime 17.57373046875
8911 usetime 26.3583984375
10585 usetime 44.912353515625
15841 usetime 48.81640625
29341 usetime 75.57153320312529342
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值