前回のコードを 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 ってもしかして絶望的に遅い?
