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

[hiroshi-manabe様の日本語訳](https://github.com/hiroshi-manabe/sicp-pdf)を使わせてもらいます。
練習問題等は[Gauche](http://practical-scheme.net/gauche/index-j.html)で実行。

[前回はこちら](https://qiita.com/shuetsu@github/items/a8593ee45392dd99fd2f)

### 練習問題1.37

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

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

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

```math
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

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

```math
\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
```