Ognacの雑感

木漏れ日々

目次

Blog 利用状況

書庫

ギャラリ

Framework4の控えめな型

新機能の影に隠れた感のありますが、新しい型に「BigInteger」があります。
有効桁数無限大(?)の整数型です。(例外はOverflowでなく OutofMemoryだそうです)
 使い道が思いつかないのですが、必要があるから実装されたと思います。
 高桁数のπの算出は手順が確立していますが、BitIntegerで計算すると
速度的にどうなるのでしようか。

ここに(http://msdn.microsoft.com/ja-jp/library/system.numerics.biginteger.aspx)
使用例がありますが、
ソースのなかに、
   BigInteger number = BigInteger.Pow(Int64.MaxValue, 2); 
   BigInteger number = Int64.MaxValue ^ 5;
の二種類の形式がありました。
この行で XORを使う意図が見えません。VBでのべき乗が "^"なので、補正し忘れているように思います。

それはともかく、サンプルを作って測定しました。( Athron 64*2 4600+)
▼Code

      BigInteger number1 = Int64.MaxValue;
      BigInteger number2 = (BigInteger)Int64.MaxValue * (BigInteger)Int64.MaxValue;
      BigInteger number3 = BigInteger.Pow(Int64.MaxValue, 2); 

      Console.WriteLine("number1[" + number1.ToString() + "]");
      Console.WriteLine("number2[" + number2.ToString() + "]");
      Console.WriteLine("number3[" + number3.ToString() + "]");
▲
▽結果
number1[9223372036854775807]
number2[85070591730234615847396907784232501249]
number3[85070591730234615847396907784232501249]
△

1000000回 Loopさせて、速度差Check
{
 BigInteger number = Int64.MaxValue; '★
 Stopwatch sw = new Stopwatch();
 sw.Start();
 for (int i = 0; i <= 回数; i++){number++;}
 sw.Stop();
 Console.WriteLine("bigInteger 所要[" + sw.ElapsedMilliseconds.ToString() + "][" + number.ToString() + "]");
}

対象の型を  BigInteger, BigInteger? , Long , Long? , Decimal , Decimal ? に変えて実行


bigInteger  所要[251msec][9223372036855775808]
bigInteger? 所要[278msec][9223372036855775808]
long        所要[  4msec][-9223372036853775808]
long?       所要[ 41msec][-9223372036853775808]
decimal     所要[ 45msec][9223372036855775808]
decimal?    所要[ 84msec][9223372036855775808]

さすがに、ネイティブな Long型が速いのは、予想通りでしたが、
decimal型の5倍程度のコストなのは、予想外に早かった。
逆に、各型のNull許容型の遅さも意外でした。

BigInt型はstring型と同様に、変更不能型で変更の都度、新しいインスタンスを作成されます。
そこで、文字型で同じ回数のLoop測定してみました。

{
 string a = "";
 Stopwatch sw = new Stopwatch();
 sw.Start();
 for (int i = 0; i <= 回数; i++)
 {
     a = i.ToString();
 }
 sw.Stop();
 Console.WriteLine("string 所要[" + sw.ElapsedMilliseconds.ToString() + "][" + a.ToString() + "]");
}

結果
string 所要[267][1000000]

ILの掃出しコードをみてませんが、数値結果から類推すると、 Biginteger,BigInteger?, string
共に、同じような値なので、文字列として演算しているような感じがします。

投稿日時 : 2010年8月2日 0:05

Feedback

# re: Framework4の控えめな型 2010/08/02 2:19 えムナウ

文字列じゃないですよ。

var b = BigInteger.Multiply(1234567890, 10000000000) + 1234567890;
Console.WriteLine(b.ToString("R"));
foreach (byte byteValue in b.ToByteArray())
Console.Write("0x{0:X2} ", byteValue);
Console.WriteLine();
b = BigInteger.Multiply(b, 10000000000) + 1234567890;
Console.WriteLine(b.ToString("R"));
foreach (byte byteValue in b.ToByteArray())
Console.Write("0x{0:X2} ", byteValue);
Console.WriteLine();
b = BigInteger.Multiply(b, 10000000000) + 1234567890;
Console.WriteLine(b.ToString("R"));
foreach (byte byteValue in b.ToByteArray())
Console.Write("0x{0:X2} ", byteValue);
Console.WriteLine();
b = BigInteger.Multiply(b, 10000000000) + 1234567890;
Console.WriteLine(b.ToString("R"));
foreach (byte byteValue in b.ToByteArray())
Console.Write("0x{0:X2} ", byteValue);

12345678901234567890
0xD2 0x0A 0x1F 0xEB 0x8C 0xA9 0x54 0xAB 0x00
123456789012345678901234567890
0xD2 0x0A 0x3F 0x4E 0xEE 0xE0 0x73 0xC3 0xF6 0x0F 0xE9 0x8E 0x01
1234567890123456789012345678901234567890
0xD2 0x0A 0x3F 0xCE 0x96 0x5F 0xBC 0xAC 0xB8 0xF3 0xDB 0xC0 0x75 0x20 0xC9 0xA0
0x03
12345678901234567890123456789012345678901234567890
0xD2 0x0A 0x3F 0xCE 0x96 0xF1 0xC7 0xF8 0x7A 0x74 0x26 0x50 0xA1 0x3C 0xF8 0xAA
0x69 0x63 0x7F 0x72 0x08

# re: Framework4の控えめな型 2010/08/02 2:27 えムナウ

12345678901234567890 が AB54A98CEB1F0AD2 なので下位から並べた感じです。

# re: Framework4の控えめな型 2010/08/02 3:02 えムナウ

そういう内容が下のほうに書いてありますよ。
http://msdn.microsoft.com/ja-jp/library/system.numerics.biginteger.aspx

# re: Framework4の控えめな型 2010/08/02 10:35 よねけん

> 使い道が思いつかないのですが、必要があるから実装されたと思います。

私の妄想では、Pythonの.NET実装のIronPythonで必要だから用意され、Pythonのためだけのクラスとするのはもったいないということでクラスライブラリに含められることになったのだろうと思っています。
#裏は取っていないのであくまで妄想ですが

元々.NET Framework3.5のときに導入される話があったのですが、一旦流れていましたね。そのときに何故流れたのかもよくはわからないのですが、そのときの残骸と思われる構造体が、System.Core.dllにSystem.Numeric.BigIntegerとして残っています。


# re: Framework4の控えめな型 2010/08/02 10:50 かたぎり

あのー、bigIntって聞いて、最初に浮かんだのが、SQLServerのBigInt型(ID設定したらできるやつ)だったので、SQL-CLR動かす時の暗黙の型変換に使うのかなぁとかふと思ったりしてみたのです。

# re: Framework4の控えめな型 2010/08/02 12:06 みきぬ

> SQLServerのBigInt型

.NET Framework でマッピングされる型は Int64 ですね。

# re: Framework4の控えめな型 2010/08/02 21:20 Ognac

ありがとうございます。
このように格納されているのですね。一種のBCD的な感じですね。
string並みのコストなのは、インスタンスコストでしょうか。
SQLサーバーの BigIntは紛らわしいですね。
同じ会社の製品なんだから名称は統一して欲しいです。

タイトル
名前
Url
コメント