SICPを読む(29) 問題1.37 - 1.39 連分数

エントリしてなかった。

連分数の問題。連分数については、連分数 - Wikipediaを参照。

共通

(define (test f a b)
  (define (iter i)
    (cond ((<= i b)
           (display (format "[~a] ~a\n" i (f i)))
           (iter (+ i 1)))))
  (iter a))

問題1.37

黄金比を見つける。

絶対解けないと思ってたのに、ちょっと考えたら解けてしまった。驚き。

再帰的パターンを見つける事が重要。

f(N_i,D_i)=\frac{Ni}{Di+f(N_{i+1},D_{i+1})}

のパターン。後はSchemeに直すだけ。

; 再帰版
(define (cont-frac n d k)
  (define (iter i)
    (if (= i k)
        (/ (n i) (d i))
        (/ (n i) (+ (d i) (iter (+ i 1))))))
  (iter 1))

; 反復版
(define (cont-frac n d k)
  (define (iter i result)
    (if (= i 0)
        result
        (iter (- i 1)
              (/ (n i) (+ (d i) result)))))
  (iter k 0))

; テスト
(test (lambda (k) 
        (cont-frac (lambda (i) 1.0)
                   (lambda (i) 1.0)
                   k))
      1 20)

(独書会の解答を見て修正を加えた)

問題1.38

eを見つけよう。

[1,2,1][1,4,1][1,6,1][1,8,1]...

というパターンを見つければ後は簡単。

僕は+2するのを忘れた(汗

(test (lambda (k) 
        (+ 2
           (cont-frac (lambda (i) 1.0)
                   (lambda (i)
                     (if (= (remainder 3 i) 2)
                         i
                         1))
                   k)))
      1 10)

問題1.39

tanを求める。

  • nは最初だけx,それ以降はxの二乗
  • dは偶数。
(define (tan-cf x k)
        (cont-frac (lambda (i)
                     (if (= i 1)
                         x
                         (* x x -1)))
                   (lambda (i) (- (* i 2) 1))
                   k))
(tan-cf 1.0 10)

まとめ

  • シンプルなパターンを見つければ連分数は簡単。
  • no lambda, no life.になりそうだ。

次節で更に深く迫ろう。