2017年10月26日木曜日

πの計算

ライプニッツの公式




実行結果
$ runghc l.hs
3.140592653839793

マチンの公式によるπ


参考にしたページ
http://handasse.blogspot.com/2011/12/1.html

Parallel版

1万桁では差がでないので
10万桁ほど計算します。

コンパイルします。

ghc  --make -O2 pm.hs -rtsopts -threaded -eventlog

CPUはCore2Duo。デュアルコアなので -N2 オプションで実行します。
$./pm +RTS -N2 -l
threadscope で動作を確認します。
$ threadscope pm.eventlog

僅かですが速くなっています。
並列計算を効率よく利用するには最初から並列化を意識してコードを書く必要があるようです。

spigot アルゴリズムをLoopで書いたコード
kk62526 さんが10進Basicで書いたコードをそのまま移植しています。

グローバル変数 「i(注)」に現在何桁目を計算しているかが保持されてますので(ただし+2された数字)
(注: 本当は無名ですが、こう捉えたほうが分かりやすいです。)
if (i-2) `mod` 100 == 0 then ・・・・・・
のようなコードを挿めば100桁ごとに区切ったりできます。
実行結果
 $ runghc p.hs > a
$ less a
3 1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679()
100 8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196()
200 4428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273()
300
~
~
~
(略)
ちなみに10000桁を計算し終えるのに2秒少々でした。
ギボンズ博士が spigot アルゴリズムに対し
"not competitive with state-of-the-art arithmetic-geometric mean algorithms"
と言うとおり決して高速とはいえませんが、いきなり1桁目から表示を始めますので、
体感的には超高速です。
(注:10000桁の計算では8万数千桁のIntegerが3つ、作られます。)

ギボンズ博士のspigot アルゴリズムは
https://www.cs.ox.ac.uk/jeremy.gibbons/publications/spigot.pdf
コードだけ紹介しますと




0 件のコメント:

コメントを投稿

Haskell Process

Haskellの System.Processは便利ですが、問題もあります。 単一スレッドでの逐次処理を保証していない。(想像です。) 次のようなスクリプトを書いてみた。 --a.hs main = print [1..10] --t.hs import Sy...