猫型エンジニアのブログ

プログラム/ネットワーク系の技術関連をまとめたページです 

問題1.6~問題1.8

問題1.6

(if ⟨predicate⟩ ⟨consequent⟩ ⟨alternative⟩)

において、predicateが真ならばconsequentを評価し、predicateが偽ならばalternativeを評価する。
つまり、consequentalternativeは必ずどちらか片方しか評価されない。

しかしnew-ifの場合、consequentalternativeも必ず評価を行う。
このときalternative

(sqrt-iter (improve guess x) x)

のsqrt-iter再帰となっているため、sqrtは無限ループとなってしまう。

処理系により結果が異なるという実例を目の当たりにして感動!

問題1.7

下の例のように平方根を求める対象の数が0.001より小さい場合は、good-enough?において適切に判定が行われない。

> (square (sqrt 0.0002))
0.0011124103413204282

good-enough?を以下のように改良するとうまくいく。

> (define 
      (good-enough? guess x)
      (< (/ (square guess)  x) 
          1.001)
      )
> (square (sqrt 0.0002))
0.0002000004105964592

大きい数の場合、有効数字の範囲内での改良が判定基準を満たさないため、無限ループになってしまうらしい。

問題1.8

improve guess x の手続きを修正する。

> (define (curt x)
    (curt-iter 1.0 x))
> (define (curt-iter guess x)
    (if (good-enough? guess x)
         guess
         (curt-iter (improve guess x) x)))
> (define (good-enough? guess x)
    (< (abs (- (cube guess) x)) 0.001))
> (define (improve guess x)
    (/
     (+ (/ x (square guess)) (* 2 guess))
     3))
> (define (cube x) (* x x x))
> (define (square x) (* x x))

動作確認

> (curt 4)
1.5874096961416333
> (cube 1.587)
3.996969003