BigInteger構造体は.NET Framework 4より使用できるようになった構造体で、長大な整数を扱うのに便利な多倍長整数型です。 BigIntegerでは扱う値の大きさに合わせて格納領域の割り当てが行われるために扱える値に理論上の上限がなく、Int64やDecimalでは扱えないサイズの整数を扱うことができるようになっています。

なお、BigInteger構造体はアセンブリSystem.Numerics.dllに含まれています。 使用する場合は、System.Numerics.dllへの参照を追加する必要があります。

§1 BigIntegerを使った例

次の例では、Int64とBigIntegerを使って1から30までの階乗を表示しています。 Int64では21!以上の値はオーバーフローするため正しくない結果が表示されていますが、BigIntegerでは正しい値が表示されています。

Int64とBigIntegerを使って階乗n!を求める
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    long lfact = 1L;
    BigInteger bifact = 1;

    for (int i = 1; i <= 30; i++) {
      lfact *= i;
      bifact *= i;

      Console.WriteLine("{0,2}! = {1,-30} {2,-20}", i, lfact, bifact);
    }
  }
}
実行結果
 1! = 1                              1                   
 2! = 2                              2                   
 3! = 6                              6                   
 4! = 24                             24                  
 5! = 120                            120                 
 6! = 720                            720                 
 7! = 5040                           5040                
 8! = 40320                          40320               
 9! = 362880                         362880              
10! = 3628800                        3628800             
11! = 39916800                       39916800            
12! = 479001600                      479001600           
13! = 6227020800                     6227020800          
14! = 87178291200                    87178291200         
15! = 1307674368000                  1307674368000       
16! = 20922789888000                 20922789888000      
17! = 355687428096000                355687428096000     
18! = 6402373705728000               6402373705728000    
19! = 121645100408832000             121645100408832000  
20! = 2432902008176640000            2432902008176640000 
21! = -4249290049419214848           51090942171709440000
22! = -1250660718674968576           1124000727777607680000
23! = 8128291617894825984            25852016738884976640000
24! = -7835185981329244160           620448401733239439360000
25! = 7034535277573963776            15511210043330985984000000
26! = -1569523520172457984           403291461126605635584000000
27! = -5483646897237262336           10888869450418352160768000000
28! = -5968160532966932480           304888344611713860501504000000
29! = -7055958792655077376           8841761993739701954543616000000
30! = -8764578968847253504           265252859812191058636308480000000


§2 演算子

BigIntegerには、四則演算・ビット演算・比較演算などの各種演算子が定義されているため、プリミティブな整数型と同じように演算式を記述することができます。

BigIntegerで使用できる主な演算子
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    BigInteger x = ulong.MaxValue;
    BigInteger y = long.MaxValue;

    // 四則演算
    Console.WriteLine("{0} + {1} = {2}", x, y, x + y);
    Console.WriteLine("{0} - {1} = {2}", x, y, x - y);
    Console.WriteLine("{0} * {1} = {2}", x, y, x * y);
    Console.WriteLine("{0} / {1} = {2:D4}", x, y, x / y);

    // 剰余
    Console.WriteLine("{0} % {1} = {2:D2}", x, y, x % y);

    // ビットシフト・ビット演算
    Console.WriteLine("{0:X} >> 3 = {1:X}", x, x >> 3);
    Console.WriteLine("{0:X} << 3 = {1:X}", y, y << 3);
    Console.WriteLine("{0:X} ^ 0xffff0000 = {1:X}", x, x ^ 0xffff0000);

    // 等値性の比較
    if (x == y)
      Console.WriteLine("x == y");
    else
      Console.WriteLine("x != y");

    // 大小関係の比較
    if (x < int.MaxValue)
      Console.WriteLine("x < int.MaxValue");
    else
      Console.WriteLine("x >= int.MaxValue");
  }
}
実行結果
18446744073709551615 + 9223372036854775807 = 27670116110564327422
18446744073709551615 - 9223372036854775807 = 9223372036854775808
18446744073709551615 * 9223372036854775807 = 170141183460469231704017187605319778305
18446744073709551615 / 9223372036854775807 = 0002
18446744073709551615 % 9223372036854775807 = 01
0FFFFFFFFFFFFFFFF >> 3 = 1FFFFFFFFFFFFFFF
7FFFFFFFFFFFFFFF << 3 = 3FFFFFFFFFFFFFFF8
0FFFFFFFFFFFFFFFF ^ 0xffff0000 = 0FFFFFFFF0000FFFF
x != y
x >= int.MaxValue

BigIntegerでは、AddメソッドMultiplyメソッドRemainderメソッドなど各演算子の代替メソッドも静的メソッドとして用意されているため、これを用いて演算することもできます。 数学関数については、Mathクラスではなく§.数学関数で解説するメソッドを用います。

上記の結果からもわかるとおり、BigIntegerでもDXなどの書式指定子がサポートされています。 書式については§.文字列への変換・書式を指定した文字列化 (ToStringメソッド)でも解説します。

また、IComparable<BigInteger>, IEquatable<BigInteger>も実装しているので、BigIntegerの配列をソートしたり、このインターフェースを使用した比較も行えます。

IComparable<T>、IEquatable<T>については大小関係の定義と比較および等価性の定義と比較を参照してください。 ソートについては基本型のソートと昇順・降順でのソートを参照してください。

§3 型変換

§3.1 数値型との相互変換

BigIntegerでは、Int32などの整数型から/への型変換を行えるようになっています。 整数型へ変換する際、値が型の値域を越えている場合はOverflowExceptionがスローされます。

BigIntegerから整数型へ型変換する
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    BigInteger bi = 3;

    int i = (int)bi;

    Console.WriteLine(i);

    bi = long.MaxValue;

    i = (int)bi;

    Console.WriteLine(i);
  }
}
実行結果
3

ハンドルされていない例外: System.OverflowException: Int32 型の値が大きすぎるか、または小さすぎます。
   場所 System.Numerics.BigInteger.op_Explicit(BigInteger value)
   場所 Sample.Main()

また、DoubleやDecimalなどの実数型からの/への変換も同様に行えます。 実数型からBigIntegerに型変換する場合、小数部は切り捨てられます。

実数型からBigIntegerへ型変換する
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    BigInteger bi;

    bi = (BigInteger)decimal.MaxValue;

    Console.WriteLine("{0} => {1}", decimal.MaxValue, bi);

    bi = (BigInteger)double.MaxValue;

    Console.WriteLine("{0} => {1}", double.MaxValue, bi);

    bi = (BigInteger)0.5;

    Console.WriteLine("{0} => {1}", 0.5, bi);
  }
}
実行結果
79228162514264337593543950335 => 79228162514264337593543950335
1.79769313486232E+308 => 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
0.5 => 0

Int32, Double, Decimalなどを引数にとるコンストラクタも用意されているので、これを使うこともできます。

コンストラクタを使ってBigIntegerへ型変換する
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    Console.WriteLine(new BigInteger(int.MaxValue));
    Console.WriteLine(new BigInteger(long.MaxValue));
    Console.WriteLine(new BigInteger(float.MaxValue));
    Console.WriteLine(new BigInteger(double.MaxValue));
    Console.WriteLine(new BigInteger(decimal.MaxValue));
  }
}
実行結果
2147483647
9223372036854775807
340282346638528859811704183484516925440
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
79228162514264337593543950335

§3.2 文字列からの変換 (Parseメソッド・TryParseメソッド)

ParseメソッドTryParseメソッドも用意されているので、文字列からBigIntegerを生成することもできます。

文字列からBigIntegerへ変換する
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    Console.Write("x? ");

    BigInteger x = BigInteger.Parse(Console.ReadLine());

    Console.Write("y? ");

    BigInteger y = BigInteger.Parse(Console.ReadLine());

    Console.WriteLine("x * y = {0}", x * y);
  }
}
実行結果
x? 10000000000000000000000000000000000000000000000
y? 654654654654987984321324168621357987
x * y = 6546546546549879843213241686213579870000000000000000000000000000000000000000000000

§3.3 文字列への変換・書式を指定した文字列化 (ToStringメソッド)

ToStringメソッドを使うことでBigIntegerの値を文字列化することができます。 また、引数に書式指定文字列を指定すれば、その書式によって文字列化することもできます。

書式を指定してBigIntegerを文字列に変換する
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    BigInteger x = BigInteger.Parse("123456789012345678901234567890");

    string str = x.ToString(); // ToStringメソッドによる文字列化

    Console.WriteLine(str);
    Console.WriteLine();

    Console.WriteLine(x.ToString("X")); // 16進数形式で文字列化
    Console.WriteLine(x.ToString("N0")); // 位取りのカンマを付けて文字列化(小数部は0桁)
    Console.WriteLine(x.ToString("E2")); // 指数形式で文字列化(小数部は2桁)
    Console.WriteLine();

    // 上記のToStringメソッドを使った場合と同じ出力結果となる
    Console.WriteLine("{0:X}", x);
    Console.WriteLine("{0:N0}", x);
    Console.WriteLine("{0:E2}",x);
    Console.WriteLine();
  }
}
実行結果
123456789012345678901234567890

18EE90FF6C373E0EE4E3F0AD2
123,456,789,012,345,678,901,234,567,890
1.23E+029

18EE90FF6C373E0EE4E3F0AD2
123,456,789,012,345,678,901,234,567,890
1.23E+029

この他に使用できる書式指定文字列や、各書式の詳細については書式指定子を参照してください。

§3.4 バイト配列への変換 (ToByteArrayメソッド)

BigIntegerをバイト配列に変換するには、ToByteArrayメソッドを使うことができます。 得られるバイト配列はリトルエンディアンになります。

BigIntegerからバイト配列へ変換する
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    BigInteger a = 1;
    BigInteger b = -1;
    BigInteger c = 256;
    BigInteger d = -256;
    BigInteger e = 0x12345678;

    Console.WriteLine(BitConverter.ToString(a.ToByteArray()));
    Console.WriteLine(BitConverter.ToString(b.ToByteArray()));
    Console.WriteLine(BitConverter.ToString(c.ToByteArray()));
    Console.WriteLine(BitConverter.ToString(d.ToByteArray()));
    Console.WriteLine(BitConverter.ToString(e.ToByteArray()));
  }
}
実行結果
01
FF
00-01
00-FF
78-56-34-12

また、BigIntegerのコンストラクタはバイト配列を引数にとるバージョンが用意されているので、バイト配列からBigIntegerを構築することもできます。

§4 値の種類

BigIntegerには、格納されている値の種類を知るための次のようなプロパティが用意されています。

IsZero
値が0かどうか。
IsOne
値が1かどうか。
IsEven
値が偶数かどうか。
IsPowerOfTwo
値が2の累乗かどうか。
Sign
値の符号を取得する。 返される値はInt32で、正なら1、負なら-1、0なら0が返される(Math.Signメソッドと同様の動作)
BigIntegerの値の種類を調べる
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    BigInteger bi = 1;

    Console.WriteLine(bi);
    Console.WriteLine("IsZero       : {0}", bi.IsZero);
    Console.WriteLine("IsOne        : {0}", bi.IsOne);
    Console.WriteLine("IsEven       : {0}", bi.IsEven);
    Console.WriteLine("IsPowerOfTwo : {0}", bi.IsPowerOfTwo);
    Console.WriteLine("Sign         : {0}", bi.Sign);
    Console.WriteLine();

    bi = -4;

    Console.WriteLine(bi);
    Console.WriteLine("IsZero       : {0}", bi.IsZero);
    Console.WriteLine("IsOne        : {0}", bi.IsOne);
    Console.WriteLine("IsEven       : {0}", bi.IsEven);
    Console.WriteLine("IsPowerOfTwo : {0}", bi.IsPowerOfTwo);
    Console.WriteLine("Sign         : {0}", bi.Sign);
    Console.WriteLine();
  }
}
実行結果
1
IsZero       : False
IsOne        : True
IsEven       : False
IsPowerOfTwo : True
Sign         : 1

-4
IsZero       : False
IsOne        : False
IsEven       : True
IsPowerOfTwo : False
Sign         : -1

なお、0+1-1の三値に相当する定数は静的プロパティとして用意されています。

"0, +1, -1"に対応する定数プロパティ
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    Console.WriteLine(BigInteger.Zero);
    Console.WriteLine(BigInteger.One);
    Console.WriteLine(BigInteger.MinusOne);
  }
}
実行結果
0
1
-1

§5 数学関数

Mathクラスに用意されている数学関数は、BigIntegerをサポートしていません。 代わりに、これらの関数はBigInteger構造体のメソッドとして提供されています。 BigIntegerには次のようなメソッドが用意されています。 Mathクラスと同様、いずれも静的メソッドです。

BigIntegerに用意されている数学関数とそれに相当するMathクラスのメソッド
関数 BigIntegerのメソッド 相当するMathクラスのメソッド
絶対値 |x| BigInteger.Abs(x) Math.Abs
最大 max(x, y) BigInteger.Max(x, y) Math.Max
最小 min(x, y) BigInteger.Min(x, y) Math.Min
商と剰余 BigInteger.DivRem(x, y, out remainder) Math.DivRem
累乗 xn BigInteger.Pow(x, n) Math.Pow
自然対数 ln x BigInteger.Log(x) Math.Log
常用対数 log10x BigInteger.Log10(x) Math.Log10
対数 logax BigInteger.Log(x, a) Math.Log
関数 BigIntegerのメソッド 相当するMathクラスのメソッド

次の例では、BigIntegerを使って5以上の階乗の値を求め、BigInteger.Log10メソッドでの桁数を求めて指数表記で表示しています。

using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    BigInteger fact = BigInteger.One;

    for (int i = 1; i <= 30; i++) {
      fact *= i;

      if (i < 5)
        continue;

      int exp = (int)BigInteger.Log10(fact);
      double mant = (double)fact / Math.Pow(10, exp);

      Console.WriteLine("{0,2}! = {1,35} ≒ {2:F2} x 10^{3}", i, fact, mant, exp);
    }
  }
}
実行結果
 5! =                                 120 ≒ 1.20 x 10^2
 6! =                                 720 ≒ 7.20 x 10^2
 7! =                                5040 ≒ 5.04 x 10^3
 8! =                               40320 ≒ 4.03 x 10^4
 9! =                              362880 ≒ 3.63 x 10^5
10! =                             3628800 ≒ 3.63 x 10^6
11! =                            39916800 ≒ 3.99 x 10^7
12! =                           479001600 ≒ 4.79 x 10^8
13! =                          6227020800 ≒ 6.23 x 10^9
14! =                         87178291200 ≒ 8.72 x 10^10
15! =                       1307674368000 ≒ 1.31 x 10^12
16! =                      20922789888000 ≒ 2.09 x 10^13
17! =                     355687428096000 ≒ 3.56 x 10^14
18! =                    6402373705728000 ≒ 6.40 x 10^15
19! =                  121645100408832000 ≒ 1.22 x 10^17
20! =                 2432902008176640000 ≒ 2.43 x 10^18
21! =                51090942171709440000 ≒ 5.11 x 10^19
22! =              1124000727777607680000 ≒ 1.12 x 10^21
23! =             25852016738884976640000 ≒ 2.59 x 10^22
24! =            620448401733239439360000 ≒ 6.20 x 10^23
25! =          15511210043330985984000000 ≒ 1.55 x 10^25
26! =         403291461126605635584000000 ≒ 4.03 x 10^26
27! =       10888869450418352160768000000 ≒ 1.09 x 10^28
28! =      304888344611713860501504000000 ≒ 3.05 x 10^29
29! =     8841761993739701954543616000000 ≒ 8.84 x 10^30
30! =   265252859812191058636308480000000 ≒ 2.65 x 10^32

また、Mathクラスでは提供されない、次のようなメソッドも用意されています。

BigInteger.ModPow(value, exponent, modulus)
次の式で得られる剰余を求めます。 valueexponent mod modulus
BigInteger.GreatestCommonDivisor(x, y)
xとyの最大公約数を求めます。

一方で、java.math.BigIntegerにあるようなmodInverseやnextProbablePrimeなどのメソッドは用意されていません。

§6 乱数

BigIntegerには乱数を生成するためのメソッドが用意されておらず、またRandomクラスもBigIntegerに対応したメソッドを持っていません。 ここではBigIntegerの乱数を生成する方法について見ていきます。 なお、以下で紹介する方法では乱数の分布等についてはあまり考慮していません。 必要とする乱数の性質に合わせて適切な方法を選んでください。

乱数の生成方法については乱数を参照してください。

§6.1 Random.NextDoubleを使う方法

BigIntegerの乱数を生成する方法にはいくつかありますが、その一つはRandom.NextDoubleメソッドを使う方法です。 次の例では、0からdouble.MaxValueまで範囲にある乱数を生成し、BigIntegerに変換しています。

Random.NextDoubleを使ってBigIntegerの乱数を取得する
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    Random rand = new Random();

    for (int i = 0; i < 10; i++) {
      // 0からdouble.MaxValueまでの乱数を取得
      BigInteger val = new BigInteger(double.MaxValue * rand.NextDouble());

      Console.WriteLine("[{0}]: {1}", i, val);
    }
  }
}
実行結果
[0]: 82098446065070156516008802208350072595314490504383488226990961977787093047512140228093296480588178848469182561244964693041601173558405848200725641188829553108217990062488995508471544291415749956295518073463357320003663833826358242419565362873425908071347196595471358469790860472070847389936409494669924237312
[1]: 159125106373833346888532116689178334185657037814698423494728732570490746875483848344797628103533988226348482728319141435706353646357712486582459088857906478848545811431392960994837354761263410723727062325450499879493329249862292564793610297868794881622382709294561067589043126240854751956620733729372167471104
[2]: 24425720459536395152412038673807295575020179457090129721418108438287180595278942282501621674304698909238977042972079615458528444698133177003978247965412513167424660497083840452587276273159791713546889603430336011958702818045071534581470550998582848022666054172810878317028414869986145334178944543332870651904
[3]: 116145450336362985322687072923306552635209274725327595812798074610837754724245153732291513822014103387542666401940898652792372336254853042114641587938076825197646705911630900221013318847296239357389764552923994602798932229382507820329873388835959152161933624167406904293894522727069866761988978094956494192640
[4]: 49430656114312776445829286722055949684073078963672663539980136807928486937699000065259145886798929660861514948291688428334441800765644979225387796440292297985266714042378489546850911315108287121513772387748103167223629322251155799576341618400954150131582561750389927568383735715502301617974957898754569535488
[5]: 163599062235324911493059876946008993511653214156530575475754606311835559435176571000548681910245808956085828572605735178662664230429391826797760090184505486371950528387960787696124274403094445676866307057063610622681275573504099893042861144771632185237204906003096001565855248032952609108871593267426649702400
[6]: 61720759976511630651119394955525127126046450840236557828065111095558514067734349681081047277471532939032994355164935986363251541221595232384773682138291443254855982960682776962708941980027548303665427306979388059844885026921576482873926448840374801634113333566489452019283760265316368390937133046254652096512
[7]: 30944481736189514555142738234766880263850378772289569292548359843626090069647422772083415974386957307872063790993553412474979526128120612471907738764647993662850837966354889662312021086851702538291948450483958854384539224460165152448832701160046792341017136619872837616960743493592210136313036920845615759360
[8]: 114457505589159584483391492407454148689000893814980965243936074425962377575702722752748083790255375940479840957095888453749181796494929653948668916029536164048158677779493168926630391332505423943593071414407215232973926609732320185704087100868948222057173797499054080854238817571324601192681123739542812098560
[9]: 8906766378429304742952410713253696387604315959790377223244985228593224411910979463047355000651563290868461657390730221957146068138908950521229627159015232016362709301711496986882807866327296855232372596843424489557156651722736719987923455411213918681582858639709767273735697029785048400915841843483048411136

ただ、この方法ではdoubleで扱える範囲を越える大きさの乱数は生成出来ません。

§6.2 Random.NextBytesを使う方法

もう一つの方法は、Random.NextBytesメソッドを使い、ランダムなビット列からBigIntegerを生成する方法です。 次の例では、0からdouble.MaxValueまで範囲にある乱数を生成し、BigIntegerに変換しています。

Random.NextBytesを使ってBigIntegerの乱数を取得する
using System;
using System.Numerics;

class Sample {
  static void Main()
  {
    Random rand = new Random();

    for (int i = 0; i < 10; i++) {
      // 256ビットのランダムなビット列を生成
      byte[] bits = new byte[32];

      rand.NextBytes(bits);

      // BigIntegerに変換
      BigInteger val = new BigInteger(bits);

      Console.WriteLine("[{0}]: {1}", i, val);
    }
  }
}
実行結果
[0]: 31028064291330346535026151635948079032369095082522834739863768437340236011080
[1]: -32550629667785318791696806315870094803545391250044371755888339672469526542675
[2]: 49815678509557472543873841157391969859324679847740358083506639519357644099320
[3]: 630672323019855186579551760740076366310457726309894294288548170790741117496
[4]: 29651103186920854548601632349177911836778182541697080309367692088137977284847
[5]: 16721155174693624114029016175151806942420375366831651736724778061290505342388
[6]: -8922837380470792087125118174969304135093453973569613283227323991664307969189
[7]: -48049234631178771981897607151534592721235468994417322257552687131763732758467
[8]: -27469885429035582987573376251452946234900188759372637407352222278483271783966
[9]: 11048698812527087192810912551820310151129964162681509215288805296886479828894

この方法では任意のビット数の乱数を生成できますが、Random.Nextメソッドのように上限・下限を指定したり、桁数を限定して生成することは出来ません。

§6.3 文字列から生成する方法

また別の方法として、文字列を使う方法があげられます。 次の例では、100桁の乱数をまず文字列として生成し、その後BigIntegerに変換しています。

ランダムな数を表現する文字列からBigIntegerの乱数を取得する
using System;
using System.Numerics;
using System.Text;

class Sample {
  static void Main()
  {
    Random rand = new Random();

    for (int i = 0; i < 10; i++) {
      StringBuilder numbers = new StringBuilder();

      // 100桁のランダムな数値を表す文字列を生成
      for (int n = 0; n < 100; n++) {
        numbers.Append(rand.Next(0, 10).ToString());
      }

      // BigIntegerに変換
      BigInteger val = BigInteger.Parse(numbers.ToString());

      Console.WriteLine("[{0}]: {1}", i, val);
    }
  }
}
実行結果
[0]: 252978269964842522533362568346227577040488410026817394808729876518963136345031447115745238731811405
[1]: 602435246356331567404902434909795191773288734828377495375141851456809328362994977358128063377009511
[2]: 4978604904194418171351685449657080873830046701682550863307087650362749124575305137978158725534880195
[3]: 8621280072810731212550781593294223217147836164852287801539801960345819378978177529428562976805415748
[4]: 2077082625909042816198436291986451610475656787378124751745088896934226812595091883000858227710643183
[5]: 6450283743252710680403390361211347620290168824320281871307498074156456638758467638722069506673388033
[6]: 753903640711332341375116984854726926480728230456494288248464973253993777742333440010409349644394170
[7]: 6122993073254977520302197555749369295042979037457739321352093364446350305291897403481661573243982612
[8]: 8573704515637261824529231731586372766119747953911150125474504231716772160202897798644406569848813482
[9]: 5944263781419806853572947116038015288738552987991697344489148630699003793759840232465271838770151538