問題 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 まで減少させていき、連分数の深いほうから浅い方に向かって計算していきます。これは計算のしやすさの事情です。
個人的には再帰プロセスで書くほうが好きです。