- 1.1.7節で作成した、sqrtの弱点を解析せよ
- また、その弱点を改良せよ
とりあえず、検証用手続きを作る
(define (sqrt-test x) (/ (square (sqrt x)) x))
非常に小さい数の場合、閾値よりも小さい数になると精度が悪くなる。
再帰が少ない回数で終了してしまうため
(sqrt-test 0.001) ==> 1.70118517210756 (sqrt-test 0.0001) ==> 10.4383583352337
非常に大きい数の場合、何回繰り返しても目標閾値に達成しないため、
無限ループに陥る
(sqrt-test 10000000000000) ==>無限ループ
改良版good-enough?
; 変化率が一定以下になればOK (define (good-enough? guess x) (< (change-rate guess x) 0.001)) ; 現在の予測値との変化率を求める (define (change-rate guess x) (/ (change-value guess x) guess)) ; 変化量を求める (define (change-value guess x) (abs (- guess (improve guess x))))
ばっちり
(sqrt-test 0.001) ; 1.00121716823195 (sqrt-test 0.0001) ; 1.00014281284086 (sqrt-test 10000000000000) ; 1.00009859407248 (sqrt-test 100000000000000000) ; 1.00000505272809
もちろんAnswerBookはより素敵な回答。
自分のはgood-enough?の引数を変えずに頑張っているため、improveが再帰一回に付き2回呼ばれてしまっている。
AnswerBookはsqrt-iterの引数を3つにすることで、improveが一回で済むようになり、かつ全体の構造もすっきりしている。