; ======================================================================
;
; Structure and Interpretation of Computer Programs
; (trial answer to excercises)
;
; 计算机程序的构造和解释(习题试解)
;
; created: code17 02/28/05
; modified:
; (保持内容完整不变前提下,可以任意转载)
; ======================================================================
;; SICP No.1.23
;; 定义next函数,改动find-divisor定义
(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 n)
(if (= n 2) 3 (+ n 2)))
;; Test-it:
;; Welcome to MzScheme version 209, Copyright (c) 2004 PLT Scheme, Inc.
;; > (search-for-primes 1000 3)
;;
;; 1001
;; 1003
;; 1005
;; 1007
;; 1009 *** 0.027099609375
;; 1011
;; 1013 *** 0.02685546875
;; 1015
;; 1017
;; 1019 *** 0.026123046875
;; finish
;;
;; > (search-for-primes 10000 3)
;;
;; 10001
;; 10003
;; 10005
;; 10007 *** 0.071044921875
;; 10009 *** 0.072021484375
;; 10011
;; 10013
;; 10015
;; 10017
;; 10019
;; 10021
;; 10023
;; 10025
;; 10027
;; 10029
;; 10031
;; 10033
;; 10035
;; 10037 *** 0.071044921875
;; finish
;;
;; > (search-for-primes 100000 3)
;;
;; 100001
;; 100003 *** 0.222900390625
;; 100005
;; 100007
;; 100009
;; 100011
;; 100013
;; 100015
;; 100017
;; 100019 *** 0.218017578125
;; 100021
;; 100023
;; 100025
;; 100027
;; 100029
;; 100031
;; 100033
;; 100035
;; 100037
;; 100039
;; 100041
;; 100043 *** 0.2177734375
;; finish
;;
;; 根据两次测试数据
;; 1000 10000 100000
;; 1 0.039 0.115 0.363
;; 2 0.026 0.071 0.219
;; 我们可见第2种算法用时并非达到第一种的50%左右,而是60%-65%之间
;; 这是因为,尽管第二种算法的递归次数减小一半,但每次递归的成本增加了,
;; next函数每次都要进行函数调用,并进行条件判断,这增加了一定的成本。
;;
;; 如果需要测试:在不考虑next的成本的前提下,是否真的可以将时间缩短一半
;; 我们可以进行如下改动: 将text-divisor直接每次(+ 2)不再使用next函数,
;; 而初始测试数改为3,这样的改动在程序逻辑上是错误的,因为某些仅可以被2
;; 整除的书将被判断为质数,我们仅对3,5,7,9..进行判断。但是,对于那些本
;; 身就是质数的数,其执行过程是不变的,而且判断的数字正好减少一半,其他
;; 什么都不变。而我们要观测的正是那些质数的判断时间。改动如下
;; (define (find-divisor n test-divisor)
;; (cond ((> (square test-divisor) n) n)
;; ((divides? test-divisor n) test-divisor)
;; (else (find-divisor n (+ 2 test-divisor)))))
;; (define (smallest-divisor n)
;; (find-divisor n 3))
;; 经过测试t(1000)=0.21, t(10000)=0.59 t(100000)=0.181,差不多正好
;; 是第一次测试中的一半时间。