1.3
中文版中的“两个数之和”应修改为“两个数之平方和”
1.4 ((if (> b 0) + -) a b)
运算符可做为复合表达式的组成部分。
中文版中写“复合表达式的组合式”表述不准确,根据搜索,发现复合表达式就是组合式,原文应该是想表达composition组成部分的意思。
1.5
(define (p) (p))
(define (test x y)
(if (= x 0)
0
y))
(test 0 (p))
应用序会陷入死循环,因为它会优先求出(p)的值,再去展开test。
正则序的话就是我们的普通思路,为0.
此题可结合1.6对应用序和正则序进行更深理解。
1.6
懒得再敲代码
复制人家写好得一段测试代码
(cond (pred thenc)
(else elsec)))
(define (iter x y)
(new-if ( = x y)
0
(iter (+ x 1 ) y)))
(define (iter-if x y)
(if ( = x y)
0
(iter-if (+ x 1 ) y)))
(define (iter-cond x y)
(cond (( = x y) 0 )
(else (iter-cond (+ x 1 ) y))))
这里有三种方法, cond 与 if 可正常求平方根,new-if 会无限递归。
new-if 的stack overflow的原因同1.5,就是因为会先对else分支语句的iter求值再展开new-if,而在iter递归会成为无限递归。
而if 与 cond 不会出错的原因就是scheme会对自己系统定义的标识符优先识别。
可尝试执行
(define (new-if pred thenc elsec)
(cond (pred thenc)
(else elsec)))
(define (p) (p))
(if (= 1 1) 1 (p)) //立刻输出1
(new-if (= 1 1) 1 (p)) //stack overflow
1.7
(define (average x y) (/ (+ x y) 2))
(define (improve guess x)
(average guess (/ x guess)))
(define (sqrt-iter a b x)
(if (good? a b)
b
(sqrt-iter b (improve b x) x )))
(define (sqrt x) (sqrt-iter x 1 x))
(define (good? a b)
(> 0.00001 (abs (- a b))))
(sqrt 0.00000001)
> 9.799734463768972e-4
(sqrt 1e300)
> 1.0000000000000002e150
可见对于很大很小的数都能工作。
1.8
(define (sqr x) (* x x)) (define (cube a b x) (if (good? a b) b (cube b (f b x) x))) (define (f y x) (/ (+ (/ x (sqr y)) (* 2 y)) 3)) (define (cub x) (cube x 1 x))
即利用1.7的good?函数。(define (good? a b) (> 0.00001 (abs (- a b))))
(cub 8) > 2.000000000012062 (cub 27) > 3.0000000000000976
1.9
显而易见,或者自己简单动一下手都可以发现,第一个是递归,第二个是迭代。
1.10
(A 1 10) = 1024
(A 2 4) = 65536
(A 3 3) = 65536
---------------------
(f n) = 2*n
(g n) = 2^n
(h n) = 2^(2^(n-1)) n = 1,2,3,4.......
0 n = 0
以下为原版的Ackermann函数, 可见函数定义与原题有不同。
原图居然挂了。。早知保存一份下来上传。。
Ackermann 函数 此处可用于探讨如上或者如原题那样的递归却又非原始递归的函数如何用迭代形式实现。
参见:http://baike.baidu.com/view/2463172.htm http://en.wikipedia.org/wiki/Ackermann_function
原始递归: http://zh.wikipedia.org/zh/%E5%8E%9F%E5%A7%8B%E9%80%92%E5%BD%92%E5%87%BD%E6%95%B0#.E5.AE.9A.E4.B9.89
自己mark之,回头看。
1.11
递归方法
(define (f n) (cond ((< n 3) n) (else (+ (f (- n 1)) (* 2 (f (- n 2))) (* 3 (f (- n 3)))))))
迭代方法
(define (f n) (fun 0 1 2 n 2)) (define (fun a b c n count) (cond ((< n 3) n) ((= count n) c) (else (fun b c (+ c (* 2 b) (* 3 a)) n (+ count 1)))))
或者把fun函数放进f函数定义块里可省去一个n参数,即(fun a b c count)
1.12
中文版要求为计算三角形,纳闷了一下去search,发现要求应为计算pascal三角中的元素pascal(n,k)。
此处假定输入的(pas n k)必然为合法下三角输入。(define (pas n k) (cond ((or (= n k) (= k 1)) 1) (else (+ (pas (- n 1) (- k 1)) (pas (- n 1) k)))))
1.13
普通求数列通项方法求Fibonacci通项
F(n) = F(n-1) + F(n-2)
F(n) - c* F(n-1) = k * ( F(n-1) - c * F(n-2) )
Let FI1 = (1 + sqrt(5))/2 FI2 = (1 - sqrt(5))/2
求得 c = FI1 , k = FI2 或c = FI2 , k = FI1 —— c , k 具有等效替代性
取 c = FI1 , k = FI2 :
1.14
这题一开始想错了。。认为硬币是有顺序的,结果树也画错了。
别人正确的树:http://telegraphics.com.au/~toby/sicp/ex1-14.svg
计算增长阶也是看别人的。
1.15
a) 5次。 0.1 * 3^4 < 12.15 < 0.1 * 3^5
b) 原过程为线性递归过程。故空间与调用sine过程次数有关。而sine的调用为 floor(log3(a)),即空间和步数的增长的阶均为O(log N)
1.16
(define (fast-expt b n) (fast-iter 1 b n)) (define (fast-iter a b n) (cond ((= n 0) 1) ((= n 1) a) ((even? n) (fast-iter (* a b b) b (/ n 2))) (else (fast-iter (* a b) b (- n 1)))))
1.17 && 1.18语文太差,实在没懂1.17 和 1.18题意有什么区别。。所以做了应该是1.18的,懂了1.18的话1.17应该也没有问题。。
(define (double x) (+ x x)) (define (halve x) (/ x 2)) (define (fast-sum b n) (sum-iter 0 b n)) (define (sum-iter a b n) (cond ((= n 1) a) ((even? n) (sum-iter (+ a (double b)) b (/ n 2))) (else (sum-iter (+ a b) b (- n 1)))))
1.19a0
b0
a1 = b0*q + a0*q + a0*p
b1 = b0*p + a0*q
a2 = b1*q + a1*q + a1*p = ... = b0*(q^2 + 2*p*q) + a0*(p+q)^2
b2 = b1*p + a1*q = b0*(p^2 + q^2) + a0*(p+q)^2
As for Fibonacci, T(q, p) = T(1, 0), That is
A(k) = A(k-1) + B(k-1)
B(k) = A(k-1)
Substitute (1, 0) with (q, p) in the source code of the Textbook Ex1.19.
Then that is the fast-Fibonacci method with steps of O(logN) level.
1.20
1.21
(define (prime? n) (= (smallest-divisor n) n)) (define (smallest-divisor n) (find-divisor n 2)) (define (divides? a b) (= (remainder a b) 0)) (define (square n) (* n n)) (define (find-divisor n test) (cond ((> (square test) n) n) ((divides? n test) test) (else (find-divisor n (+ test 1)))))
199 => 199
1999 => 1999
19999 => 7
1.22