Exercise 3.59
sin, cos の無限級数展開の各項を要素として持つストリームを求める問題です。
a)
まずは無限多項式 における係数のストリーム a0 a1 a2 ... を引数にとり、多項式を積分したときの係数を返す関数 integrate-series を考える問題です。
ストリームの各要素に処理を施すのは stream-map で。
(define (integrate-series a) (stream-map (let1 n 0 (lambda (x) (inc! n) (/ x n))) a))
こんな感じ。
(use util.stream) (define (add-streams s1 s2) (stream-map + s1 s2)) (define ones (stream-cons 1 ones)) (define integers (stream-cons 1 (add-streams ones integers))) (define (integrate-series a) (stream-map (let1 n 0 (lambda (x) (inc! n) (* (/ 1 n) x))) a)) (define b (integrate-series ones)) (let loop ((i 0)) (unless (= i 10) (print (stream-ref b i )) (loop (+ i 1))))
を実行すると
1 1/2 1/3 1/4 1/5 1/6 1/7 1/8 1/9 1/10
となります。OK ですね。
b)
e^x は積分しても自分自身なので、再帰的に次のように表すことができる。
(define exp-series (stream-cons 1 (integrate-series exp-series)))
これを利用して cos, sin を表してみる。
なので、
(define cosine-series (stream-cons 1 (stream-map (let1 n 0 ;; exp-series の 第 n 項について (lambda (x) (inc! n) (if (= (modulo n 2) 0) (* (if (= (modulo n 4) 0) 1 -1) x) 0))) (stream-cdr exp-series)))) (define sine-series (stream-cons 0 (stream-map (let1 n 0 ;; exp-series の 第 n 項について (lambda (x) (inc! n) (if (= (modulo n 2) 0) 0 (* (if (= (modulo n 4) 1) 1 -1) x)))) (stream-cdr exp-series))))
と表すことができる。
が、ちがった。
sin の微分が cos で、 cos の微分が -sin ということを利用しないといけないのね。問題は良く読みましょう。
ということで作り直し。
(define cosine-series (stream-cons 1 (stream-map (lambda (x) (* -1 x)) (integrate-series sine-series)))) (define sine-series (stream-cons 0 (integrate-series cosine-series)))
ということですね。
実際に動かしてみる
(define i 0) (until (= i 10) (format #t "~s " (stream-ref exp-series i )) (inc! i)) (format #t "\n") (set! i 0) (until (= i 10) (format #t "~s " (stream-ref sine-series i )) (inc! i)) (format #t "\n") (set! i 0) (until (= i 10) (format #t "~s " (stream-ref cosine-series i )) (inc! i)) (format #t "\n")
1 1 1/2 1/6 1/24 1/120 1/720 1/5040 1/40320 1/362880 0 1 0 -1/6 0 1/120 0 -1/5040 0 1/362880 1 0 -1/2 0 1/24 0 -1/720 0 1/40320 0
あってるようです。