暇なので復習するシリーズ ~連分数展開~

問題 1.37

(a)nとdを一引数(項の添字i)で連分数の項のNiとDiを返す手続きとする。(cont-frac n d k)がk項有限連分数を計算するような手続きcont-fracを定義せよ.

(define (cont-frac-rec n d k)
  (define (rec i)
    (if (= i k)
        (/ (n k) (d k))
        (/ (n i) (+ (d i) (rec (+ i 1))))))
  (rec 1))

数式をそのまま実装すれば良いです。
再帰プロセスで書く方が直感的でわかりやすくて好きです。
(コンピュータは不満を言うかも知れませんがw)

(cont-frac (lambda (i) 1.0)
           (lambda (i) 1.0)
           k)

のkの順次の値で1/φの近似をとり, 手続きを調べよ。

gosh> (cont-frac-rec (lambda (i) 1.0) (lambda (i) 1.0) 1000)
0.6180339887498948

4桁の精度の近似を得るのに, kはどのくらい大きくしなければならないか。

gosh> (cont-frac-rec (lambda (i) 1.0) (lambda (i) 1.0) 10)
0.6179775280898876
gosh> (cont-frac-rec (lambda (i) 1.0) (lambda (i) 1.0) 11)
0.6180555555555556

4 桁の精度を近似するには、k は 11 以上にしなければならない。

(b)cont-fracが再帰的プロセスを生成するなら, 反復的プロセスを生成するものを書け. 反復的プロセスを生成するなら, 再帰的プロセスを生成するものを書け.

再帰プロセス版は既出になりますが、両方を見比べやすくするために両方を載せます。

(define (cont-frac-rec n d k)
  (define (rec i)
    (if (= i k)
        (/ (n k) (d k))
        (/ (n i) (+ (d i) (rec (+ i 1))))))
  (rec 1))

(define (cont-frac-iter n d k)
  (define (iter i cf)
    (if (= i 0)
        cf
        (iter (- i 1) (/ (n i) (+ (d i) cf)))))
  (iter k (/ (n k) (d k))))

再帰プロセスのほうは手続きの引数に計算結果を持たないので、 i は 1 から始めて k まで増加させていき、連分数の浅い部分から深い部分へ向かって計算をしていきます。他方、反復プロセスのほうは手続きの引数に計算結果を持たせるため、i は k から始めて 1 まで減少させていき、連分数の深いほうから浅い方に向かって計算していきます。これは計算のしやすさの事情です。
個人的には再帰プロセスで書くほうが好きです。