Java言語の Integer
やDouble
型は表せる桁数が決まっています.Integer
は
32ビット,Long
でも64ビットであるため,それぞれ,$-2^{31}〜2^{31} - 1$,$-2^{63}〜2^{63} - 1$
までの値までしか扱えません.
Javaでは任意桁の計算が行える型が存在します.任意桁の整数を表すBigInteger
と任意桁の実数を表すBigDecimal
です.
これらを扱ってみましょう.
任意桁の整数を表す型です.BigInteger
を利用するときは,import java.math.BigInteger;
というimport
文が必要です.BigInteger
型の実体を作成するときは,new BigInteger("表したい数")
のように数値を文字列で指定してください.
この型を扱うとき,通常の四則演算が使えない点に注意してください.
BigInteger value1 = new BigInteger("10");
BigInteger value2 = new BigInteger("20");
BigInteger value3 = value1.add(value2);
// BigInteger value4 = value1 + value2;
// => コンパイルエラー.
プログラム中でInteger
型の値をBigInteger
として扱いたい場合や,
その逆があります.
以下のプログラムのように,相互変換が可能です.
Integer intValue = 10;
// Integer型からBigInteger型へ変換する.
BigInteger bigValue = BigInteger.valueOf(intValue);
// BigInteger型からInteger型へ変換する.
// もし,bigValue が大きすぎて 32ビットに収まらない場合は,下位32ビットのみが返される.
Integer intValue2 = bigValue.intValue();
上記のように,足し算は add
というメソッド呼び出しで実現します.
以下に対応を掲載します.どれも BigInteger
型の変数b1
とb2
を使って計算しているものとします.
b1 + b2
)
b1.add(b2)
b1 - b2
)
b1.subtract(b2)
b1 * b2
)
b1.multiply(b2)
b1 / b2
)
b1.divide(b2)
b1 % b2
)
b1.remainder(b2)
-b1
)
b1.negate()
b1.compareTo(b2)
b1
の方が小さければ,負の整数.
b1 < b2
ならば b1.compareTo(b2) < 0
b1
の方が大きければ,正整数.
b1 > b2
ならば b1.compareTo(b2) > 0
0
.
b1 == b2
ならば b1.compareTo(b2) == 0
なお,BigDecimal
も基本的にはBigInteger
と同じです.
メソッド呼び出しで演算を行い,実体を作成するときは,実数を表す文字列を渡せば良いです.
先ほど示した計算方法を実際にプログラムに書いてみましょう.2つのBigInteger
型の変数
import java.math.BigInteger;
public class BigOperator{
void run(){
BigInteger b1 = new BigInteger("10"); // BigInteger型の実体を作成する.
BigInteger b2 = BigInteger.valueOf(3); // Integer型からBigInteger型へ変換する.
BigInteger result1 = b1.add(b2); // b1 + b2
BigInteger result2 = b1.subtract(b2); // b1 - b2
BigInteger result3 = b1.multiply(b2); // b1 * b2
BigInteger result4 = b1.divide(b2); // b1 / b2
BigInteger result5 = b1.remainder(b2); // b1 % b2
BigInteger result6 = b1.negate(); // -b1
System.out.printf("%s + %s = %s%n", b1, b2, result1); // <= 13
System.out.printf("%s - %s = %s%n", b1, b2, result2); // <= 7
System.out.printf("%s * %s = %s%n", b1, b2, result3); // <= 30
System.out.printf("%s / %s = %s%n", b1, b2, result4); // <= 3
System.out.printf("%s %% %s = %s%n", b1, b2, result5); // <= 1
System.out.printf("-%s = %s%n", b1, result6); // <= -10
if(b1.compareTo(b2) > 0){ // b1 > b2
System.out.println("b1 の方が b2 より大きい.");
}
}
}
第2回目の練習問題 3. 階乗 を改良し,
桁あふれを起こさないようにしましょう.
前回作成した階乗のプログラムは,13!
を正確に計算できません.これを BigInteger
を使って,
どんな数値が与えられたとしても計算できるようにしてください.
クラス名をBigFactorial
としてください.
コマンドライン引数から値を受け取れるようにしましょう.
また,コマンドライン引数で受け取る値はInteger
型として扱って良いです.
$ java Factorial 12 # => 前回のプログラム.正しい結果の限界.
12! = 479001600
$ java Factorial 13 # => 前回のプログラム.正しくない結果.
13! = 1932053504
$ java BigFactorial 11
11! = 39916800
$ java BigFactorial 12 13 14 15
12! = 479001600
13! = 6227020800
14! = 87178291200
15! = 1307674368000