前回のコードを C# で書いてみようと何故か思った。
書いていて気がついたのだが C# は百桁程度の整数も扱えない。
そういえば C++ も扱えない、今まで int64 までしか使ったこともない。
あぁ GMP ってそのことだったんだ。
Python や Ruby の整数は桁数が無限なので気がつかなかった。
てゆーか無限に扱える意味ってようするに数学の世界だと。
多倍長整数っていうんだね。
ググると BigInteger というのが見つかった。
CodeProject: C# BigInteger Class. Free source code and programming help
まあよく解らないものは使って覚えるのが一番早い。
クラスなので普通に new したあとは整数のように扱えるはず。
落としてプロジェクトに含めてみる。
いきなり困った、べき乗 Math.Pow() は double しか扱えない。
いや、考えてみたら計算は Math でやらなきゃいけないわけではない。
自分で for ループさせても何も問題無い、ここまではすぐに思いついた。
でもそれをどう計算…つまらないことに詰まってしまったり。
なんとか百桁に成功したところで一万桁とかにすると例外スロー。
private const int maxLength = 70;
この数値が関係あるらしい、大きな桁にするときは増やして使う。
まあとりあえずそんなこんなで書いてみたコード。
using System; using System.Diagnostics; namespace pi1 { class Test { // System.Numeric.BigInteger はまだない BigInteger p, q; BigInteger expansion(int n) { BigInteger x, nn, c, s, k; x = new BigInteger(0); nn = new BigInteger(0); c = new BigInteger(0); s = new BigInteger(0); k = new BigInteger(0); x = (p * q) / n; nn = n * n; c = 1; s = x; k = 1; while (x > 0) { x = x / nn; k = k + 2; c = -c; s = s + c * (x / k); } return s; } public void pie() { Console.WriteLine("円周率を計算します。"); Console.WriteLine("桁数を指定してください"); int prsn = int.Parse(Console.ReadLine()); p = new BigInteger(1); q = new BigInteger(1); Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 1; i <= prsn; i++) p *= 10; for (int i = 1; i <= 10; i++) q *= 10; BigInteger y, u, v; y = new BigInteger(0); u = new BigInteger(0); v = new BigInteger(0); y = 4 * ( 12 * expansion(18) + 8 * expansion(57) - 5 * expansion(239) ); y = y / q; u = y / p; v = y - u * p; sw.Stop(); Console.WriteLine("{0}.{1}", u, v); Console.WriteLine("計算時間={0}", sw.ElapsedMilliseconds / 1000.0); Console.Read(); } } class Program { static void Main(string[] args) { Test t = new Test(); t.pie(); } } }
初期化の引数は BigInteger でもいいはずだけど怖いので int に。
あまり意味は無い。
IronPython より十倍速いわな、BigInteger が早いのだろうか。
それよりやはり .NET もコンパイルしたほうが早いということだろうけど。
とはいえ CPython にはボロ負けのまま…
せめてマルチスレッド化したほうが…意味があるかは置いておいて。
実用アプリじゃ全く問題無いことだし。
C 言語は面倒くさいので上記のとかを試す。
百万桁でたったの 39 秒だもの、この差をどうこうしようとか思わないわ。
手元に IronPython 1.1 が残っていたので前回のコードを試す。
0.098 秒…あれ?二倍も速くなった、DLR ってもしかして絶望的に遅い?