ずいぶん前に Hutton の Haskell 本を読んで、階乗くらいしかプログラムを書かずに放置していましたが、夏にもう一度勉強しようかなと思ってみました。
とりあえず Fortran で書いた 分割数 p(n) の直接計算を移植してみることにしました。文法をよく知らないのでものすごく時間がかかりました。結果が微妙におかしい感じがしますが、デバッグ・プリントが難しくてあきらめました。
実行結果
インストールするのもかったるいのでオンライン・コンパイラにて。
Free Online IDE and Terminal
1から10までの分割数、1,2,3,5,7,11,15,22,30,42 を計算しています。
sh-4.3$ ghc -O2 --make *.hs -o main -threaded -rtsopts [1 of 1] Compiling Main ( main.hs, main.o ) Linking main ... sh-4.3$ main [0.9810639,2.0009859,3.0242445,5.014357,6.9633565,11.030045,14.987319,21.990871,30.022284,41.988766] sh-4.3$ ^C
ソース・プログラム
複素数の使い方が分からなくて泣きました。型変換がよく分からなくて・・・
import Data.Complex dsn :: RealFloat a => Int -> a -> a dsn k z = ( f * cosh(f * x) - sinh(f * x) / x ) / (2 * x * x) where f = pi / fromIntegral k * sqrt(2.0 / 3.0) x = sqrt(z - 1.0 / 24.0) f :: RealFloat a => Int -> Int -> Int -> a -> Complex a f n k h x = (sqrt (fromIntegral k) / (pi * sqrt 2.0) :+ 0.0) * exp (0:+ x) * (dsn k (fromIntegral n):+ 0.0) w :: Int -> Int -> Int -> Float w n k h = pi * (w1 n k h + w2 k h) w1 :: Int -> Int -> Int -> Float w1 n k h = (-2.0) * (fromIntegral n) * (fromIntegral h) / (fromIntegral k) w2 :: Int -> Int -> Float w2 k h = sum [(fromIntegral j) / (fromIntegral k) * (frac ((fromIntegral h) * (fromIntegral j) / (fromIntegral k)) - 0.5) |j <- [1..k-1]] frac :: Float -> Float frac x = x - fromIntegral (floor x) gg :: Int -> [Complex Float] gg n = [f n k h (w n k h) | k <- [1..], h <- [1..k], gcd k h == 1] partition :: Int -> Float partition n = realPart ( sum (take max_k (gg n)) ) where max_k = 10 main = print ([partition i| i <- [1..10]])