【Java】任意精度整数(多倍長整数)で演算する 
2016/01/27 Wed [edit]
べき乗の計算などをしていると、必ずぶつかるのは桁あふれ(オーバフロー)の問題。幸いにも Java には始めから任意精度整数(BigInteger / BigDecimal)があるのだが、なぜかあまりサクッと使い方を一覧できるような資料が見つからなかったので、超簡単にまとめてみた。
■値の定義
BigInteger a, b, c;
//基本的に文字列で値を割り当てる
a = new BigInteger("123456789");
a = new BigInteger("-98765"); //負の値
//プリミティブ型→文字列に変換して値を割り当てる
long x = 123456789;
b = new BigInteger(String.valueOf(x));
//定数で値を割り当てる
c = BigInteger.ZERO; //0
c = BigInteger.ONE; //1
c = BigInteger.TEN; //10
■演算
●加算: a + b
//c = a + b
c = a.add(b);
●減算: a - b
//c = a - b
c = a.subtract(b);
●乗算: a * b
//c = a * b
c = a.multiply(b);
●除算: a / b
//c = a / b
c = a.divide(b);
●剰余: a % b
//c = a % b
c = remainder(b);
●べき乗: an (n:int)
//c = an (n:int)
c = a.pow(n);
■結果
●文字列に変換: toString() で表示できる。
//文字列型: c.toString()
System.out.println(c); //toString() と同義
●数値に変換
//double 型
double d = c.doubleValue(); //指数形式になる。上から16桁より下は丸められる(0で埋まる)ので注意。
//long 型 (※オススメできない)
long l = c.longValue(); //下19桁が取り出される。上の桁が削られるので注意。桁が大きいと大抵 0 になってしまう。
■比較
●等号: a == b, a != b
//a == b
if (a.equals(b)) {
//equal
} else {
//not equal (!equal)
}
//または
if (a.compareTo(b) == 0) {
//equal
} else {
//not equal (!= 0)
}
//※ if (a == b) は参照の比較なので、false になる。
●不等号: a < b, a <= b, a > b, a >= b
//a < b
if (a.compareTo(b) < 0) {
//a < b
} else {
//a >= b
}
//※ <=, >, >= なども同様
●小さい方をとる: min(a, b)
//c = min(a, b)
c = a.min(b);
●大きい方をとる: max(a, b)
//c = max(a, b)
c = a.max(b);
●絶対値: abs(a)
//c = abs(a)
c = a.abs();
他にもビット演算(&, |, xor, ~)、ビットシフト(<<, >>, >>>)などもあるが、使い方は同じようなものなので、公式リファレンスで確認すると良いだろう。
BigInteger は String と同じように「変更できない値」となるので、演算するたび新しいオブジェクトが生成され、処理は非常に重い。大量の計算をするときには注意した方が良いだろう(余談だが、String も「a + b」のような演算をするたび new されている。大量に連結する場合は StringBuilder で append() した方が良いだろう。GC稼働も少なくなる)。
参考までに私の環境(Windows10/Intel Core i5 x64 2.9GHz)での BigInteger の階乗計算にかかった時間は、
100000! で、2822 [ms]
1000000! で、356593 [ms] (約6分)
だった。10万回を超える演算には注意した方が良いかもしれない。
ちなみに任意精度符号付き10進数の「BigDecimal」の方は実数のように扱える。使い方はほぼ同じだ。また、BigInteger より約30% ほど速いようだ。
(関連記事)
【Java】1000000!のような巨大な階乗計算をする [任意精度整数(多倍長整数)]
【Java】プリミティブ型での階乗計算
【Java】順列の数を求める
【Java】組合せの数を求める
【Java】フィボナッチ数(数列)を求める
- 関連記事
トラックバック
トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/197-398c7e7e
この記事にトラックバックする(FC2ブログユーザー)
| h o m e |