SICP 1.21-1.28

寻找因子法

(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)))

练习1.21

(smallest-divisor 199)
199

(smallest-divisor 1999)
1999

(smallest-divisor 19999)
7

练习1.22
检测prime的运行时间

(define (runtime)
        (time->seconds (current-time)))

(define (timed-prime-test n)
  (newline)
  (display n)
  (start-prime-test n (runtime)))

(define (start-prime-test n start-time)
  (if (prime? n)
      (report-prime (- (runtime) start-time))))

(define (report-prime elapsed-time)
  (display " *** ")
  (display elapsed-time))

解题

(define (search-for-primes start count)
  (define (search-for-primes-iter n count)
    (if (= 0 count)
        (newline)
        (if (prime? n)
            (begin (timed-prime-test n) (search-for-primes-iter (+ n 2) (- count 1)))
            (search-for-primes-iter (+ n 2) count))))

  (if (odd? start)
      (search-for-primes-iter start count)
      (search-for-primes-iter (+ start 1) count)))
> (search-for-primes 1000 3)
1009 *** 2.8848648071289062e-5
1013 *** 2.6702880859375e-5
1019 *** 2.6464462280273438e-5
> (search-for-primes 10000 3)
10007 *** 8.463859558105469e-5
10009 *** 8.225440979003906e-5
10037 *** 8.988380432128906e-5
> (search-for-primes 100000 3)
100003 *** 2.63214111328125e-4
100019 *** 2.5534629821777344e-4
100043 *** 2.7489662170410156e-4
> (search-for-primes 1000000 3)
1000003 *** 8.673667907714844e-4
1000033 *** 8.487701416015625e-4
1000037 *** 8.304119110107422e-4
> (search-for-primes 10000000 3)
10000019 *** .0018930435180664062
10000079 *** .0021266937255859375
10000103 *** .001911163330078125

练习1.23

(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 (next test-divisor)))))

(define (next test-divisor)
  (if (= test-divisor 2)
      3
      (+ test-divisor 2)))

(define (divides? a b)
  (= (remainder b a) 0))

(define (prime? n)
  (= n (smallest-divisor n)))
> (search-for-primes 1000 3)
1009 *** 2.0265579223632812e-5
1013 *** 2.1696090698242188e-5
1019 *** 2.1696090698242188e-5
> (search-for-primes 10000 3)
10007 *** 6.079673767089844e-5
10009 *** 5.698204040527344e-5
10037 *** 5.9604644775390625e-5
> (search-for-primes 100000 3)
100003 *** 1.6808509826660156e-4
100019 *** 1.633167266845703e-4
100043 *** 1.6307830810546875e-4
> (search-for-primes 1000000 3)
1000003 *** 5.249977111816406e-4
1000033 *** 5.125999450683594e-4
1000037 *** 5.097389221191406e-4
> (search-for-primes 10000000 3)
10000019 *** .0016429424285888672
10000079 *** .0016353130340576172
10000103 *** .0010938644409179688

练习1.24

费马定理: 如果n是一个素数,a是小于n的任意正整数,那么a的n次方与a模n同余。
(如果两个数除以n的余数相同,称为模n同余)
0 < a < n => a  n   mod n = a mod 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)
  (define (try-it a)
    (= (expmod a n n) a))
  (try-it (random-integer n)));random-integer是Gambit-c提供的函数

(define (fast-prime? n times)
  (cond ((= times 0) #t)
        ((fermat-test n) (fast-prime? n (- times 1)))
        (else #f)))
(define (runtime)
        (time->seconds (current-time)))

(define (timed-prime-test n)
  (newline)
  (display n)
  (start-prime-test n (runtime)))

(define (start-prime-test n start-time)
  (if (fast-prime? n 5)
      (report-prime (- (runtime) start-time))))

(define (report-prime elapsed-time)
  (display " *** ")
  (display elapsed-time))

(define (search-for-primes start count)
  (define (search-for-primes-iter n count)
    (if (= 0 count)
        (newline)
        (if (fast-prime? n 3)
            (begin (timed-prime-test n) (search-for-primes-iter (+ n 2) (- count 1)))
            (search-for-primes-iter (+ n 2) count))))

  (if (odd? start)
      (search-for-primes-iter start count)
      (search-for-primes-iter (+ start 1) count)))
> (search-for-primes 1000 3)
1009 *** 7.772445678710938e-5
1013 *** 8.20159912109375e-5
1019 *** 8.988380432128906e-5
> (search-for-primes 10000 3)
10007 *** 1.010894775390625e-4
10009 *** 9.560585021972656e-5
10037 *** 9.894371032714844e-5
> (search-for-primes 100000 3)
100003 *** 1.1563301086425781e-4
100019 *** 1.1944770812988281e-4
100043 *** 1.1801719665527344e-4
> (search-for-primes 1000000 3)
1000003 *** 1.354217529296875e-4
1000033 *** 1.3875961303710938e-4
1000037 *** 1.361370086669922e-4
> (search-for-primes 10000000 3)
10000019 *** 1.5854835510253906e-4
10000079 *** 1.671314239501953e-4
10000103 *** 1.6617774963378906e-4

练习1.25

(define (expmod base exp m)
  (remainder (fast-expt base exp) m))

这样会比1.24运行的慢


练习1.26
(expmod base (/ exp 2) m)被递归两次


练习1.27
能够骗过费马检查的数,称为Carmichael数,在100000000之内有255个Carmichael数,其中最小的几个是561、1105、1729、2465、2821和6601。

> (fast-prime? 561 10)
#t

> (fast-prime? 1105 5)
#t

> (fast-prime? 1729 5)
#t

> (fast-prime? 2465 5)
#t

> (fast-prime? 2821 5)
#t

> (fast-prime? 6601 5)
#t

练习1.28

(define (mr n)
  (define (test-all-a count result)
    (display count) (display result) (newline)
    (if result
      (if (> count 1)
        (test-all-a (- count 1) (try-it (- count 1))) ;test all a, 1 < a < n
        #t)
      #f))
  (define (try-it a)
    (= (expmod a (- n 1) n) 1))
  (test-all-a n #t)) 

(define (expmod base expo m)
  (cond ((= expo 0) 1)
        ((even? expo) (let* ((x (expmod base (/ expo 2) m)) (r (remainder (square x) m)))
                          (if (and (= r 1) (not (= x 1)) (not (= x (- m 1)))) 0 r)))
        (else (remainder (* base (expmod base (- expo 1) m))
                         m))))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
"SICP中文版"是指计算机科学经典教材《Structure and Interpretation of Computer Programs》(计算机程序构造解释)的中文翻译PDF版。这本教材由麻省理工学院的Harold Abelson和Gerald Jay Sussman等人编写,是计算机科学领域中一本重要的教材。 "SICP中文版PDF"提供了更方便的学习方式。无论是学生、程序员还是计算机科学爱好者,都可以在任何时候通过电子设备访问和学习这本教材。使用PDF格式的好处是可以在不同的平台上都能打开和阅读,而不受限于特定的操作系统或设备。 通过"SICP中文版PDF",读者可以学习计算机科学的基本原理和概念,如过程、数据抽象、递归、高阶函数、并发等。这本教材以Scheme语言为示例,帮助读者理解计算机程序的结构、设计和解释。通过逐步的案例和练习,读者可以锻炼解决问题和编写高质量代码的能力。 "SICP中文版PDF"也提供了沟通和讨论的平台。读者可以通过在线社群或论坛,与其他人分享学习心得、解答疑问和参与讨论。这为读者提供了一个学习交流的机会,促进了学习者之间的互动和共同成长。 总之,"SICP中文版PDF"是一本经典的计算机科学教材的中文翻译版本,使得更多的读者可以方便地学习和掌握其中的知识。无论是对于计算机科学专业的学生还是对计算机科学感兴趣的人,这本教材都是一本很好的参考书,并提供了丰富的实例和练习,让读者深入理解计算机程序的核心概念和设计原则。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值