kagamihogeの日記

kagamihogeの日記です。

java.math.BigInteger探訪

今回はまだぜんぜんソース読めてません・・・。デバッガで動かしてどういう動きするか、ぐらいしか見てないです。
そろそろ次の仕事の準備に時間取られてくので、API探訪は終了かな。でも、いつかはJavaの世界に戻ってきたいと今は思ってるので、Javaを忘れないように続けていきたいなぁ。

BigIntegerは多倍長整数をどう表現しているか

やり方としては(たぶん)一般的な方法。int配列で1つの値を表します。

//BigIntegerからインスタンス変数を抜粋
int signum;
int[] mag;//magnitude の略記

signumは符号をあらわします。正、負、ゼロの3値です。

それはともかくとして、magの方です。intの配列として宣言はしてますが、便宜上のものです。配列要素のビットをぜんぶ繋げた状態で1つの整数、という使い方をします。

たとえば、配列数2のmagの中がこうだったとします。

要素 [0] [1]
整数 -1 1
ビット 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0001

これは、18446744069414584321を示しています。関数電卓で2進数1111111111111111111111111111111100000000000000000000000000000001を10進数に変換してみるとわかります。

こんな感じに、intと宣言してるけれどもプリミティブのintとして扱わずに中身のビット表現の連なりに着目する、という使い方で多倍長整数を表現しています。

BigIntegerは整数をどこまで扱えるか

Javaのintは32ビット。フツーにプリミティブ型として扱う場合、2^31-1から-2^31と大体±21億ぐらい。

それに対してBigIntegerは符号を別の変数で扱うので、補数を考える必要がなく、32ビット使える*1

で、int配列の1桁で±42億ぐらいが扱える。2桁使うと2^64=18446744073709551616・・・約1.8垓。さすがに京より上は単位がわからんかった・・・。

というわけで、常識的な範囲で計算する分には十分な数を格納できるのが分かりました。そりゃ計算速度はプリミティブでやるのに比べて遅くなるだろうけど。

オマケ:何桁まで扱えるか

果たしてBigIntegerはどこまでの整数を扱えるのか。ちょーどうでもいいことを考えてみました。

配列要素数がintの限界値まで取れるとすると*2、2147483647要素が限界となる。このとき、2^2147483647-1という値まで扱えるようになるわけだけど・・・いくつなんだ、これ・・・。

次に、これだけの領域を確保するには・・・

2147483647(要素) * 32(ビット)
= 68719476704 bit / 8
= 8589934588 byte
= 約8589934 KB
= 約8589 MB
= 約8.5 GB

なんだか無駄にわくわくしますね。

*1:2^32-1

*2:突っ込み所満載な前提条件だが、お遊びなので許してくれ