计算机程序的构造和解释(SICP) 第1章 习题解析 Part3
这次回顾第一章剩余全部习题。
学习资料:
https://github.com/DeathKing/Learning-SICP
https://mitpress.mit.edu/sites/default/files/sicp/index.html
https://www.bilibili.com/video/BV1Xx41117tr?from=search&seid=14983483066585274454
参考资料:
https://sicp.readthedocs.io/en/latest
参考资料:
https://sicp.readthedocs.io/en/latest
1.29(p39)
记
那么
从而得到代码:
(define (sum term a next b)
(if (> a b)
0
(+ (term a)
(sum term (next a) next b))))
(define (cube x) (* x x x))
(define (simpson f a b n)
(define h (/ (- b a) n))
(define (g a0)
(+ (f a0)
(* 4 (f (+ a0 h)))
(f (+ a0 (* 2 h)))))
(define (next a) (+ a (* 2 h)))
(* (sum g a next b)
(/ h 3)))
(display (simpson cube 0 1.0 100))
(newline)
(display (simpson cube 0 1.0 1000))
0.25000000000000044
0.2500000000000006
1.30(p40)
(define (sum term a next b)
(define (iter a result)
(if (> a b)
result
(iter (next a) (+ result (term a)))))
(iter a 0))
1.31(p40)
定义
那么
定义
代码如下:
(define (product1 term a next b)
(if (> a b)
1
(* (term a)
(product1 term (next a) next b))))
(define (product2 term a next b)
(define (iter a result)
(if (> a b)
result
(iter (next a) (* result (term a)))))
(iter a 1))
;; factorial
(define
(term a) a)
(define
(next a) (+ a 1))
(define (factorial product n)
(product term 1 next n))
(display "Factorial: ")
(newline)
(display "Product1: ")
(display (factorial product1 5))
(newline)
(display "Product2: ")
(display (factorial product2 5))
(newline)
;; pi
(define (square x)
(* x x))
(define (term 2k)
(/ (* 2k (+ 2k 2)) (square (+ 2k 1))))
(define (next 2k)
(+ 2k 2))
(define (pi product n)
(* 4 (product term 2.0 next (* 2 n))))
(display "Pi: ")
(newline)
(display "Product1: ")
(display (pi product1 100))
(newline)
(display "Product2: ")
(display (pi product2 100))
结果如下:
Factorial:
Product1: 120
Product2: 120
Pi:
Product1: 3.1493784731686008
Product2: 3.149378473168601
1.32(p40)
; 递归
(define (accumulate1 combiner null-value term a next b)
(if (> a b)
null-value
(combiner (term a) (accumulate1 combiner null-value term (next a) next b))))
; 迭代
(define (accumulate2 combiner null-value term a next b)
(define (iter a result)
(if (> a b)
result
(iter (next a) (combiner result (term a)))))
(iter a null-value))
; sum
(define (sum term a next b)
(define (combiner a b)
(+ a b))
(define null-value 0)
(accumulate1 combiner null-value term a next b))
; prod
(define (product term a next b)
(define (combiner a b)
(* a b))
(define null-value 1)
(accumulate1 combiner null-value term a next b))
; test
; test for sum
(define (cube x) (* x x x))
(define (simpson f a b n)
(define h (/ (- b a) n))
(define (g a0)
(+ (f a0)
(* 4 (f (+ a0 h)))
(f (+ a0 (* 2 h)))))
(define (next a) (+ a (* 2 h)))
(* (sum g a next b)
(/ h 3)))
(display "Test for accumulate1 and sum:")
(newline)
(display (simpson cube 0 1.0 100))
(newline)
(display (simpson cube 0 1.0 1000))
(newline)
; test for prod
(define (square x)
(* x x))
(define (term 2k)
(/ (* 2k (+ 2k 2)) (square (+ 2k 1))))
(define (next 2k)
(+ 2k 2))
(define (pi product n)
(* 4 (product term 2.0 next (* 2 n))))
(display "Test for accumulate2 and product:")
(newline)
(display "Pi: ")
(display (pi product 100))
结果:
Test for accumulate1 and sum:
0.25000000000000044
0.2500000000000006
Test for accumulate2 and product:
Pi: 3.1493784731686008
1.33(p40)
对之前的代码稍微修改即可,这里(a)的函数包含上下界$a,b$:
;; prime?
(define (square a)
(* a a))
(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.33
(define (filtered-accumulate combiner filter null-value term a next b)
(cond ((> a b) null-value)
((filter a) (combiner (term a) (filtered-accumulate combiner filter null-value term (next a) next b)))
(else (filtered-accumulate combiner filter null-value term (next a) next b))))
; a
(define (prime-sum a b)
(define (combiner a b)
(+ a b))
(define (filter a)
(prime? a))
(define null-value 0)
(define (term a)
a)
(define (next a)
(+ a 1))
(filtered-accumulate combiner filter null-value term a next b))
; 2 + 3 + 5 + 7 = 17
(display "Test for a: ")
(display (prime-sum 2 10))
(newline)
; b
(define (gcd a b)
(if (= b 0)
a
(gcd b (remainder a b))))
(define (n-prime-sum n)
(define (combiner a b)
(+ a b))
(define (filter a)
(= (gcd a n) 1))
(define null-value 0)
(define (term a)
a)
(define (next a)
(+ a 1))
(filtered-accumulate combiner filter null-value term 2 next n))
; 3 + 7 + 9 = 19
(display "Test for b: ")
(display (n-prime-sum 10))
(newline)
结果如下:
Test for a: 17
Test for b: 19
1.34(p44)
(define (square x)
(* x x))
(define (f g)
(g 2))
; 等价于(square 2)
(display (f square))
(newline)
; 等价于((lambda (z) (* z (+ z 1))) 2)
(display (f (lambda (z) (* z (+ z 1)))))
(newline)
; (f f)报错, 等价于(f 2)
结果如下:
4
6
1.35(p47)
求解方程可得:
所以结论成立。
对应代码:
(define tolerance 0.00001)
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess)
(let ((next (f guess)))
(if (close-enough? guess next)
next
(try next))))
(try first-guess))
(display (fixed-point (lambda (x) (+ 1 (/ 1 x))) 1.0))
结果如下:
1.6180327868852458
1.36(p47)
(define tolerance 0.00001)
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess n)
(display n)
(display "th iteration: ")
(display guess)
(newline)
(let ((next (f guess)))
(if (close-enough? guess next)
next
(try next (+ n 1)))))
(try first-guess 0))
(display "平均阻尼情形:")
(newline)
(fixed-point (lambda (x) (/ (+ x (/ (log 1000) (log x))) 2)) 2.0)
(display "不用平均阻尼情形:")
(newline)
(fixed-point (lambda (x) (/ (log 1000) (log x))) 2.0)
结果如下:
平均阻尼情形:
0th iteration: 2.0
1th iteration: 5.9828921423310435
2th iteration: 4.922168721308343
3th iteration: 4.628224318195455
4th iteration: 4.568346513136242
5th iteration: 4.5577305909237005
6th iteration: 4.555909809045131
7th iteration: 4.555599411610624
8th iteration: 4.5555465521473675
不用平均阻尼情形:
0th iteration: 2.0
1th iteration: 9.965784284662087
2th iteration: 3.004472209841214
3th iteration: 6.279195757507157
4th iteration: 3.759850702401539
5th iteration: 5.215843784925895
6th iteration: 4.182207192401397
7th iteration: 4.8277650983445906
8th iteration: 4.387593384662677
9th iteration: 4.671250085763899
10th iteration: 4.481403616895052
11th iteration: 4.6053657460929
12th iteration: 4.5230849678718865
13th iteration: 4.577114682047341
14th iteration: 4.541382480151454
15th iteration: 4.564903245230833
16th iteration: 4.549372679303342
17th iteration: 4.559606491913287
18th iteration: 4.552853875788271
19th iteration: 4.557305529748263
20th iteration: 4.554369064436181
21th iteration: 4.556305311532999
22th iteration: 4.555028263573554
23th iteration: 4.555870396702851
24th iteration: 4.555315001192079
25th iteration: 4.5556812635433275
26th iteration: 4.555439715736846
27th iteration: 4.555599009998291
28th iteration: 4.555493957531389
29th iteration: 4.555563237292884
30th iteration: 4.555517548417651
31th iteration: 4.555547679306398
32th iteration: 4.555527808516254
33th iteration: 4.555540912917957
1.37(p47)
(define (cont-frac1 n d k)
(define (cont-frac-iter i)
(if (= i k)
(/ (n k) (d k))
(/ (n i) (+ (d i) (cont-frac-iter (+ i 1))))))
(cont-frac-iter 1))
; (a) 找到k
(define tolerance 0.00001)
(define phi-1 (/ 1 1.6180327868852458))
(define (findk f n d)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (findk-iter k)
(if (close-enough? (f n d k) phi-1)
k
(findk-iter (+ k 1))))
(findk-iter 1))
; (a) 递归法
(display
(cont-frac1 (lambda (i) 1.0)
(lambda (i) 1.0)
10))
(newline)
(display "k is ")
(display
(findk cont-frac1 (lambda (i) 1.0)
(lambda (i) 1.0)))
(newline)
; (b) 迭代
(define (cont-frac2 n d k)
(define (cont-frac-iter i res)
(if (< i 1)
res
(cont-frac-iter (- i 1) (/ (n i) (+ (d i) res)))))
(cont-frac-iter k 0))
(display
(cont-frac2 (lambda (i) 1.0)
(lambda (i) 1.0)
10))
结果如下:
0.6179775280898876
k is 12
0.6179775280898876
1.38(p47)
$D_i$的计算公式如下:
代码如下:
(define (cont-frac n d k)
(define (cont-frac-iter i)
(if (= i k)
(/ (n k) (d k))
(/ (n i) (+ (d i) (cont-frac-iter (+ i 1))))))
(cont-frac-iter 1))
(define (d i)
(define r (remainder (- 2 i) 3))
(define k (/ (- i 2 r) 3))
(cond ((< i 3) i)
((= r 0) (* 2 (+ 1 k)))
(else 1)))
(display
(+ 2 (cont-frac (lambda (i) 1.0) d 10)))
结果如下:
2.7182817182817183
1.39(p48)
注意到有如下试试
所以取
然后利用之前的过程即可,代码如下:
(define (cont-frac n d k)
(define (cont-frac-iter i)
(if (= i k)
(/ (n k) (d k))
(/ (n i) (+ (d i) (cont-frac-iter (+ i 1))))))
(cont-frac-iter 1))
(define (tan-cf x k)
(/ (cont-frac (lambda (i) (- (* x x)))
(lambda (i) (- (* 2 i) 1.0)) k)
(- x)))
(display (tan-cf 10 100))
(newline)
(display (tan 10))
结果如下:
0.6483608274590866
0.6483608274590866
1.40(p51)
; fixed-point
(define tolerance 0.00001)
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess)
(let ((next (f guess)))
(if (close-enough? guess next)
next
(try next))))
(try first-guess))
; deriv
(define (deriv g)
(lambda (x)
(/ (- (g (+ x dx)) (g x))
dx)))
(define dx 0.00001)
; newton method
(define (newton-transform g)
(lambda (x)
(- x (/ (g x) ((deriv g) x)))))
(define (newtons-method g guess)
(fixed-point (newton-transform g) guess))
; cubic
(define (cubic a b c)
(lambda (x)
(+ (* x x x) (* a x x) (* b x) c)))
(define (root a b c)
(newtons-method (cubic a b c) 1))
; test
(display (root -1 0 2))
结果如下:
-0.9999999999999872
1.41(p51)
(define (double f)
(lambda (x) (f (f x))))
(define (inc x)
(+ x 1))
(display ((double inc) 5))
(newline)
(display (((double double) inc) 5))
(newline)
(display (((double (double double)) inc) 5))
(newline)
(display (((double (double (double double))) inc) 5))
结果如下:
7
9
21
261
结果说明:
定义
下面用数学归纳法证明:
其中
当$n=0$时,
所以结论成立。
假设$n=k$时结论成立,那么$n=k+1$时,
所以$n=k+1$时结论也成立。
1.42(p51)
(define (compose f g)
(lambda (x) (f (g x))))
(define (square x)
(* x x))
(define (inc x)
(+ x 1))
; test
(display ((compose square inc) 6))
结果如下:
49
1.43(p51)
利用递归即可:
(define (compose f g)
(lambda (x) (f (g x))))
(define (repeated f n)
(if (= n 1)
f
(compose f (repeated f (- n 1)))))
(define (square x)
(* x x))
(display ((repeated square 2) 5))
结果如下:
625
1.44(p51)
(define (compose f g)
(lambda (x) (f (g x))))
(define (repeated f n)
(if (= n 1)
f
(compose f (repeated f (- n 1)))))
(define (square x)
(* x x))
(define dx 0.00001)
(define (smooth f)
(lambda (x) (/ (+ (f (- x dx)) (f x) (f (+ x dx))) 3)))
(define (nth-smooth f n)
((repeated smooth n) f))
; test
(display ((smooth square) 1.1))
(newline)
(display ((nth-smooth square 5) 1.1))
结果如下:
1.2100000000666669
1.2100000003333333
1.45(p52)
; fixed-point
(define tolerance 0.0000001)
(define (fixed-point f first-guess)
(define (close-enough? v1 v2)
(< (abs (- v1 v2)) tolerance))
(define (try guess)
(let ((next (f guess)))
(if (close-enough? guess next)
next
(try next))))
(try first-guess))
; average-damp
(define (average-damp f)
(lambda (x) (average x (f x))))
(define (average x y)
(/ (+ x y) 2))
; repeated
(define (compose f g)
(lambda (x) (f (g x))))
(define (repeated f n)
(if (= n 1)
f
(compose f (repeated f (- n 1)))))
; exp
(define (expt b n)
(if (= n 0)
1
(* b (expt b (- n 1)))))
; k次阻尼
(define (kth-average-damp f k)
((repeated average-damp k) f))
; nth-root
(define (nth-root x n k)
(fixed-point (kth-average-damp (lambda (y) (/ x (expt y (- n 1)))) k) 1.0))
(display (nth-root 5 4 2))
(newline)
结果如下:
1.4953487812212205
1.46(p52)
(define (iterative-improve good-enough? improve)
(define (iterative-improve-iter x)
(if (good-enough? x)
x
(iterative-improve-iter (improve x))))
iterative-improve-iter)
; sqrt
(define (square x)
(* x x))
(define (average x y)
(/ (+ x y) 2))
(define (sqrt x)
(define (good-enough? guess)
(< (abs (- (square guess) x)) 0.0001))
(define (improve guess)
(average guess (/ x guess)))
((iterative-improve good-enough? improve) 1.0))
(display (sqrt 2.0))
(newline)
; fixed-point
(define tolerance 0.00001)
(define (fixed-point f first-guess)
(define (good-enough? guess)
(< (abs (- (f guess) guess)) tolerance))
(define (improve guess)
(average guess (f guess)))
((iterative-improve good-enough? improve) 1.0))
(define (sqrt-fixed-point x)
(fixed-point (lambda (y) (average y (/ x y)))
1.0))
(display (sqrt-fixed-point 2.0))
(newline)
结果如下:
1.4142156862745097
1.4142047060743028
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Doraemonzzz!
评论
ValineLivere