Exercise 3.59

Exercise 3.59.

sin, cos の無限級数展開の各項を要素として持つストリームを求める問題です。

a)

まずは無限多項式 a_0+a_1x+a_2x^2+a_3\cdots における係数のストリーム 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 を表してみる。

e^x = 1 + x + \frac{x^2}{2} + \frac{x^3}{3\cdot2} + \frac{x^4}{4\cdot3\cdot2} + \cdots
\cos x = 1 -  \frac{x^2}{2} + \frac{x^4}{4\cdot3\cdot2} - \cdots
 \sin x = x - \frac{x^3}{3\cdot2} + \frac{x^5}{5\cdot4\cdot3\cdot2} - \cdots

なので、

(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

あってるようです。