计算机程序的构造和解释(SICP) 第3章 习题解析 Part8
这次回顾第三章第八部分习题。
学习资料:
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
http://community.schemewiki.org/?SICP-Solutions
http://community.schemewiki.org/?sicp
3.73(p239)
对应的关系为:
这一这里$i$是电流的含义,为了避免和整数搞混,这里将其替换为$x_i$,另外,根据题目中积分的定义,上式的实际含义为
取
那么
在代码中,$v_0+\frac 1 C \sum_{j=1}^i x_j dt$利用积分表示,$ Rx_i$利用流表示,其中为了保证$i=0$时结论成立,在$Rx_i$对应的流中补充一个$0$,最后得到代码
(load "stream.scm")
(define (RC R C dt)
(define (f input v0)
(let ((scale-input (scale-stream input (/ 1 C))))
(add-streams (integral scale-input v0 dt)
(scale-stream (cons-stream 0 input) R))))
f)
; test
(define RC1 (RC 5 1 0.5))
(define input (integers-starting-from 1))
(define v0 0)
(define output (RC1 input v0))
(stream-head output 5)
结果如下:
1 ]=> (stream-head output 5)
;Value 13: (0 5.5 11.5 18. 25.)
3.74(p240)
代码:
(load "stream.scm")
(define (sign-change-detector a b)
(cond ((and (>= a 0) (< b 0)) -1)
((and (>= b 0) (< a 0)) 1)
(else 0)))
(define (zero-crossings sense-data)
(stream-map sign-change-detector sense-data (stream-cdr sense-data)))
; test
(define sense-data
(cons-stream 1
(cons-stream 2
(cons-stream -1
(cons-stream -1
(cons-stream 2 integers))))))
(define res (zero-crossings sense-data))
(stream-head sense-data 6)
(stream-head res 6)
结果如下:
1 ]=> (stream-head sense-data 6)
;Value 13: (1 2 -1 -1 2 1)
1 ]=> (stream-head res 6)
;Value 14: (0 -1 0 1 0 0)
3.75(p240)
参考资料:
http://community.schemewiki.org/?sicp-ex-3.75
假设初始流为$\{a_i\}_{i=0}^{\infty}$,那么该方法的到的流为
但是我们的目标是得到流
在函数中记录$a_i$即可,这里人为补充$a_0=0$,代码如下
(load "stream.scm")
(load "helper.scm")
(define (make-zero-crossings input-stream last-value last-avpt)
(let ((avpt (/ (+ (stream-car input-stream) last-value) 2)))
(cons-stream (sign-change-detector last-avpt avpt)
(make-zero-crossings (stream-cdr input-stream)
(stream-car input-stream)
avpt))))
(define (smooth input-stream)
(scale-stream
(add-streams input-stream
(cons-stream 0 input-stream))
0.5))
(define (zero-crossings sense-data)
(make-zero-crossings (stream-cdr sense-data)
(stream-car sense-data)
0))
; test
(define sense-data
(cons-stream 1
(cons-stream 2
(cons-stream -1
(cons-stream -1
(cons-stream 2 integers))))))
(define smooth-data (smooth sense-data))
(define res (zero-crossings sense-data))
(stream-head sense-data 6)
(stream-head smooth-data 6)
(stream-head res 6)
结果如下:
1 ]=> (stream-head sense-data 6)
;Value 13: (1 2 -1 -1 2 1)
1 ]=> (stream-head smooth-data 6)
;Value 14: (.5 1.5 .5 -1. .5 1.5)
1 ]=> (stream-head res 6)
;Value 15: (0 0 -1 1 0 0)
3.76(p240)
前一题中已经使用了这种观点,注意这里假设$a_0=0$,代码如下
(load "stream.scm")
(load "helper.scm")
(define (smooth input-stream)
(scale-stream
(add-streams input-stream
(cons-stream 0 input-stream))
0.5))
; test
(define sense-data
(cons-stream 1
(cons-stream 2
(cons-stream -1
(cons-stream -1
(cons-stream 2 integers))))))
(define smooth-data (smooth sense-data))
(define res (zero-crossings smooth-data))
(stream-head sense-data 6)
(stream-head smooth-data 6)
(stream-head res 6)
结果如下
1 ]=> (stream-head sense-data 6)
;Value 13: (1 2 -1 -1 2 1)
1 ]=> (stream-head smooth-data 6)
;Value 14: (.5 1.5 .5 -1. .5 1.5)
1 ]=> (stream-head res 6)
;Value 15: (0 0 -1 1 0 0)
3.77(p242)
代码:
(load "stream.scm")
(define (solve f y0 dt)
(define y (integral (delay dy) y0 dt))
(define dy (stream-map f y))
y)
(define (integral delayed-integrand initial-value dt)
(cons-stream initial-value
(let ((integrand (force delayed-integrand)))
(if (stream-null? integrand)
the-empty-stream
(integral (delay (stream-cdr integrand))
(+ (* dt (stream-car integrand))
initial-value)
dt)))
))
; test
(stream-ref (solve (lambda (y) y) 1 0.001) 1000)
结果如下:
1 ]=> ; test
(stream-ref (solve (lambda (y) y) 1 0.001) 1000)
;Value: 2.716923932235896
3.78(p242)
对于微分方程
取
那么该微分方程对应的特征方程为
所以通解为
取
可得
所以
后续代码实验中应该符合上述讨论:
(load "stream.scm")
(load "delay-integral.scm")
(define (solve a b y0 dy0 dt)
(define y (integral (delay dy) y0 dt))
(define dy (integral (delay ddy) dy0 dt))
(define ddy (add-streams
(scale-stream dy a)
(scale-stream y b)))
y)
; test
(stream-head (solve 1 2 2 1 0.001) 6)
(stream-ref (solve 1 2 2 1 0.001) 0)
(stream-ref (solve 1 2 2 1 0.001) 1000)
; 理论结果
(+ (exp 0) (exp 0))
(+ (exp 2) (exp -1))
结果如下:
1 ]=> ; test
(stream-head (solve 1 2 2 1 0.001) 6)
;Value 13: (2 2.001 2.002005 2.003015007 2.004030028017 2.005050070085031)
1 ]=> (stream-ref (solve 1 2 2 1 0.001) 0)
;Value: 2
1 ]=> (stream-ref (solve 1 2 2 1 0.001) 1000)
;Value: 7.742007815125568
1 ]=> ; 理论结果
(+ (exp 0) (exp 0))
;Value: 2
1 ]=> (+ (exp 2) (exp -1))
;Value: 7.756935540102093
3.79(p243)
利用前一题的结果来验证,取
得到代码
(load "stream.scm")
(load "delay-integral.scm")
(define (solve f y0 dy0 dt)
(define y (integral (delay dy) y0 dt))
(define dy (integral (delay ddy) dy0 dt))
(define ddy (stream-map f dy y))
y)
; test
(define (function a b)
(lambda (x y)
(+ (* a x)
(* b y))))
(define a 1)
(define b 2)
(define f (function a b))
(stream-head (solve f 2 1 0.001) 6)
(stream-ref (solve f 2 1 0.001) 0)
(stream-ref (solve f 2 1 0.001) 1000)
; 理论结果
(+ (exp 0) (exp 0))
(+ (exp 2) (exp -1))
结果如下
1 ]=> (stream-head (solve f 2 1 0.001) 6)
;Value 13: (2 2.001 2.002005 2.003015007 2.004030028017 2.005050070085031)
1 ]=> (stream-ref (solve f 2 1 0.001) 0)
;Value: 2
1 ]=> (stream-ref (solve f 2 1 0.001) 1000)
;Value: 7.742007815125568
1 ]=> ; 理论结果
(+ (exp 0) (exp 0))
;Value: 2
1 ]=> (+ (exp 2) (exp -1))
;Value: 7.756935540102093
3.80(p243)
参考资料:
http://community.schemewiki.org/?sicp-ex-3.80
首先验证等式$(\star)$
满足如下微分方乘
其中条件为
首先将$\frac{\mathrm{d} v_{C}}{\mathrm{~d} t}$替换可得
显然等式$(\star)$满足该条件。
其次将$\frac{\mathrm{d} i_{L}}{\mathrm{d} t}$替换可得
将
代入可得
显然等式$(\star)$满足该条件。
注意积分的定义要放在前面
3.81(p246)
参考资料:
http://community.schemewiki.org/?sicp-ex-3.81
一开始对此题的理解是传入一个command,导致比较大的困难,后来查了网上资料后发现大家都是给函数传入多个command,这样实现的难度就比较简单了:
(load "ch3support.scm")
(load "stream.scm")
(define (rand x)
(define (dispatch number command)
(cond ((eq? command 'generate) (rand-update number))
((eq? (car command) 'reset) (cadr command))
(else (error "Unknown request" command))))
(define (rand-stream commands)
(define random-numbers
(cons-stream x
(stream-map dispatch random-numbers commands)))
random-numbers)
rand-stream)
; test
(define random-init 7)
(define random-numbers (rand random-init))
(define commands
(list->stream '(generate generate (reset 1) generate)))
(stream-head (random-numbers commands) 4)
结果如下
1 ]=> (stream-head (random-numbers commands) 4)
;Value 13: (7 88 116 1)
3.82(p246)
代码
(load "helper.scm")
(load "stream.scm")
(load "rand-stream.scm")
; 线性同余发生器参数
(define a 8121)
(define b 28411)
(define m 134456)
(define (rand-update x)
(modulo (+ (* a x) b) m))
(define random-init 10)
(define random-numbers
(cons-stream random-init
(stream-map rand-update random-numbers)))
(define (experiment x1 x2 y1 y2)
(let ((a (/ (abs (- x1 x2)) 2))
(b (/ (abs (- y1 y2)) 2))
(x0 (/ (+ x1 x2) 2))
(y0 (/ (+ y1 y2) 2)))
(define (f r1 r2)
(let ((x (+ x0 (* (/ r1 (- m 1)) a)))
(y (+ y0 (* (/ r2 (- m 1)) b))))
(< (+ (/ (square (- x x0)) (square a))
(/ (square (- y y0)) (square b)))
1)))
f))
; test
(define x1 0.0)
(define x2 10.0)
(define y1 10.0)
(define y2 30.0)
(define f (experiment x1 x2 y1 y2))
(define stream
(map-successive-pairs f random-numbers))
(define pi
(stream-map (lambda (p) (* 4 p))
(monte-carlo stream 0 0)))
(stream-head pi 40)
结果如下
;Value 13: (4 4 4 4 16/5 8/3 16/7 5/2 8/3 12/5 24/11 7/3 32/13 18/7 12/5 5/2 44/17 8/3 52/19 14/5 20/7 32/11 68/23 3 76/25 40/13 28/9 22/7 92/29 16/5 100/31 13/4 36/11 54/17 16/5 29/9 116/37 60/19 124/39 16/5)