不動点探し

SICP を飛ばし飛ばし読んでいる。これは、不動点を求める関数を使って平方根を求める、というもの。以下は適当メモ。

関数 f の不動点とは、 x = f x となるような x のこと。ここで y^2 = x という式を考えると、例えば sqrt 2 は、 y^2 = 2 となるような y を求めることになる。 この式を y = x/y と変形し、さらに y = (¥a -> x / a) y と変形すると、(¥a -> x / a) という関数の不動点を求めることが、a の平方根を求めることになることがわかる。

ところが、(¥a -> x / a) の不動点をそのまま求めようとすると、無限ループに陥ってしまう。なので、 y = x/y を少し変形して、 (y+y)/2 = (y+x/y)/2 としてみる。つまり、 y = (¥a -> (y+x/a)/2) y である。これだとループに陥らずに値を求めることができる。

fixpoint f init accu = g $ iterate f init
    where g (a:b:cs) | abs (a-b) > accu = g (b:cs)
                     | otherwise        = a

mysqrt x = fixpoint (\y -> (y+x/y)/2) 1 0.0000000001
Main> mysqrt 2
1.4142135623746899
Main> sqrt 2
1.4142135623730951
Main>