円周率を計算しよう

30分プログラム、その611。http://gauc.no-ip.org/awk-users-jp/blis.cgi/DoukakuAWK_111にインスパイアされたので、円周率を計算してみよう。
元の記事と同様にwikipedia:ガウス=ルジャンドルのアルゴリズムを使うのだけれども、このアルゴリズムはパラメータが4つあって、それを各ステップで受け渡す必要がある。4つもあると、タプルで受け渡すのは厳しいので、パラメータ用のレコードを定義して、それを使うようにしてます。

使い方

*Main> take 10 piList
[2.9142137,3.1405795,3.1415927,3.1415927,3.1415927,3.1415927,3.1415927,3.1415927,3.1415927,3.1415927]

ソースコード

data Param = Param { a :: Float, b :: Float, t :: Float, p :: Float} deriving Show

toPI :: Param -> Float
initial :: Param
improve :: Param -> Param
piList :: [Float]

toPI param = (a param + b param) ** 2 / (4 * t param)
initial = Param {a = 1, b = sqrt 0.5, t = 0.25, p = 1}
improve param = Param {a = x,
                       b = y,
                       t = t param - (p param)*(a param - x)**2,
                       p = 2 * p param}
                where x = (a param + b param) / 2
                      y = sqrt $ a param * b param

piList = map toPI $ iterate improve initial