Newton法

章1.1.3にでてくるNewton法をやってみます。
Newton法とは、数xの平方根の値の予測値yがあれば、yとx/yの平均値とるという計算でさらにより路側値が得られるというものらしい。
とりあえず、本どおりに実装。

goodEnough guess x = (abs ( x - (guess * guess) )) < 0.001
improve guess x = (( x / guess ) + guess) / 2
sqrtIter guess x 
	|goodEnough guess x = guess
	|otherwise = sqrtIter ( improve guess x ) x
sqrt' x = sqrtIter 1 x

 *Main> sqrt' 3
 1.7321428571428572
 *Main> sqrt' 4
 2.0000000929222947

このやりかたでは、非常に大きい値や小さいあたいではうまくいかないらしいので、guessの変化に注目し、変化が予測値にくらべ非常に小さくなったときに停止するように作ろうというのが問題1.7。自分なりの実装。

sqrt' x = sqrtIter 1 x
goodEnough17 guess x = (abs ( 1( guess - ( improve guess x ))) < 0.0001
sqrtIter17 guess x
	|goodEnough17 guess x = guess
	|otherwise = sqrtIter17 ( improve guess x ) x
sqrt17 x = sqrtIter17 1.0 x

で、確認のためにnobsunさんのschemeでの解答を見てみると、ちょっと違う。実際に動かしてみると

 *Main> sqrt17 4
 2.0000000929222947
 *Main> sqrt17 1.0E-6
 1.0338412392442034e-3
 *Main> sqrt17 1.0E29
 3.162277660168379e14

大きい値(1.0E29)ならいっしょだが、小さい値(1.0E-6)だとダメみたい。そうか。このやりかただと、小さい値にたいして、差が小さい値とはいえないのね。なので、実装を直してみる。

goodEnough17 guess x = (abs ( 1 -( guess / ( improve guess x )))) < 0.0001
sqrtIter17 guess x
	|goodEnough17 guess x = guess
	|otherwise = sqrtIter17 ( improve guess x ) x
sqrt17 x = sqrtIter17 1.0 x
 *Main> sqrt17 1.0E-6
 1.0000001533016628e-3

これで大丈夫。問題1.8は、立方根版の実装。近似の式は、

   x/y^2+2y
   --------
      3

となるらしい。実装は、

improve18 guess x = ( ( x / (guess * guess) ) + (2 * guess)) / 3
goodEnough18 guess x = (abs ( 1-(guess / ( improve18 guess x )))) < 0.0001
qubicroot guess x 
	| goodEnough18 guess x = guess
	| otherwise = qubicroot ( improve18 guess x ) x
qubic x = qubicroot 1.0 x

 *Main> qubic 2
 1.259933493449977
 *Main> qubic 8
 2.000004911675504

nobsunさんの結果とあわないなぁ。近似の式の書き方がちがうからか。自分の解釈ならこういう式になったんだけど。naoya_tさんの解答も式が違うし。どれが正しいんだろう?