Newton法で平方根をもとめる

cf. http://hpcgi2.nifty.com/1to100pen/wiki/wiki.cgi?p=%CB%E8%C6%FCHaskell 2006-05-21

最近流行りの SICP の 1.1.7 Newton法からお題を拝借。

おわっと,流行だったのか。もしかして乗り遅れた?


上の [1..100]>>=pen さんのもそうだし,hasko さんとこ(id:hasko:20060520:1148133213)のコメントにもあるように,先に予測値のリストを作ってしまうことにしよう。

 guess x = iterate (\g -> (g + x/g) / 2.0) 1.0
 
 goodEnough eps old new = abs (1.0 - old/new) < eps
 
 find2 f i (x:xs) | f i x     = x
                  | otherwise = find2 f x xs
 
 squareRoot x = find2 (goodEnough 0.0001) x (guess x)

guess で予測値のリストを作って,goodEnough で判定。判定は新旧予測値の比を利用し,引数で指定できるようにした。
で,あとは適当な値をリストから探すだけなんだけど,ちょうどいい関数が見あたらなかったので find2 を定義してみた。
結果。

 *Main> squareRoot 4
 2.000000000000002
 *Main> squareRoot 1.0e-6
 1.0000000000000117e-3
 *Main> squareRoot 1.0e29
 3.162277660171076e14
 *Main> (squareRoot 1.0e-6) ^ 2
 1.0000000000000235e-6
 *Main> (squareRoot 1.0e29) ^ 2
 1.0000000000017057e29

ふむ,よさげ。