Posted at

SICP読書録 #14 練習問題1.37 - 練習問題1.39

More than 1 year has passed since last update.

hiroshi-manabe様の日本語訳を使わせてもらいます。

練習問題等はGaucheで実行。

前回はこちら


練習問題1.37

無限連分数というものがある。

f=\cfrac{N_1}{D_1+\cfrac{N_2}{D_2+\cfrac{N_3}{D_3+\cdots}}}

$k$で展開を打ち切るとすると。

f=\cfrac{N_1}{D_1+\cfrac{N_2}{\ddots+\cfrac{N_k}{D_k}}}

これを手続きにしよう。

nとdは、添字を引数で受け取ると対応する項の値を返す手続きだとする。

まずは再帰プロセス版。


_.scm

(define (cont-frac n d k)

(define (iter i)
(if (> i k)
0
(/ (n i) (+ (d i) (iter (+ i 1))))))
(iter 1))

反復プロセス版。数える順を逆にする必要がある。


_.scm

(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))

以下の手続きで $1/\varphi=0.6180339...$ の近似値を求めることができる。


_.scm

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


kをどれだけ大きすれば、小数点以下4桁の制度が得られるか?


_.scm

gosh> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 5)

0.625
gosh> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 6)
0.6153846153846154
gosh> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 7)
0.6190476190476191
gosh> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 8)
0.6176470588235294
gosh> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 9)
0.6181818181818182
gosh> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 10)
0.6179775280898876
gosh> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 11)
0.6180555555555556
gosh> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 12)
0.6180257510729613
gosh> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 13)
0.6180371352785146
gosh> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 14)
0.6180327868852459
gosh> (cont-frac (lambda (i) 1.0) (lambda (i) 1.0) 15)
0.6180344478216819

11以上。


練習問題1.38

連分数展開によって、$e-2=0.71828...$の近似値を求められる。

$N_i$を全て1。$D_i$を$1,2,1,1,4,1,1,6,1,1...$とすればいいらしい。


_.scm

(define (napier k)

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

実行結果。


_.scm

gosh> (napier 5)

2.71875
gosh> (napier 6)
2.717948717948718
gosh> (napier 7)
2.7183098591549295
gosh> (napier 8)
2.718279569892473
gosh> (napier 9)
2.718283582089552
gosh> (napier 10)
2.7182817182817183


練習問題1.39

以下の式で、正接(タンジェント)を計算できる。

\tan{x}=\cfrac{x}{1-\cfrac{x^2}{3-\cfrac{x^2}{5-\cdots}}}

再帰プロセス版。


_.scm

(define (tan-cf x k)

(define (iter i)
(if (> i k)
0
(/ (if (= i 1) x (* x x))
(- (* i 2) 1 (iter (+ i 1))))))
(iter 1))

反復プロセス版。


_.scm

(define (tan-cf x k)

(define (iter i result)
(if (= i 0)
result
(iter (- i 1)
(/ (if (= i 1) x (* x x))
(- (* i 2) 1 result)))))
(iter k 0))

組み込みの tan 手続きと比較しながら実行してみよう。


_.scm

gosh> (tan-cf 0.1 10)

0.10033467208545055
gosh> (tan 0.1)
0.10033467208545055
gosh> (tan-cf 0.2 10)
0.2027100355086725
gosh> (tan 0.2)
0.20271003550867248
gosh> (tan-cf 0.3 10)
0.3093362496096232
gosh> (tan 0.3)
0.3093362496096232
gosh> (tan-cf 0.4 10)
0.4227932187381618
gosh> (tan 0.4)
0.4227932187381618
gosh> (tan-cf 0.5 10)
0.5463024898437905
gosh> (tan 0.5)
0.5463024898437905
gosh> (tan-cf 0.6 10)
0.6841368083416923
gosh> (tan 0.6)
0.6841368083416923
gosh> (tan-cf 0.7 10)
0.8422883804630793
gosh> (tan 0.7)
0.8422883804630793
gosh> (tan-cf 0.8 10)
1.0296385570503641
gosh> (tan 0.8)
1.029638557050364
gosh> (tan-cf 0.9 10)
1.2601582175503392
gosh> (tan 0.9)
1.260158217550339
gosh> (tan-cf 1.0 10)
1.557407724654902
gosh> (tan 1.0)
1.557407724654902