こんにちは。「Javaを復習する初心者」です。
掛け算九九の表を拡張しようと思い、入力値に従って9×9の掛け算の結果の表を出力しようと考えました。前半はint型でやりましたという話で、後半はBigIntegerを使ったという話です。
int型を使う
掛け算九九は1から9の数を掛け算した結果した表です。これ拡張して入力値nに対して、nからn+8の掛け算の結果を表にしようと考えました。計算結果をそのまま出力すると桁が揃わない箇所が出てきます。そこでprintfメソッドを使い、書式文字列を指定します。通常の1から9の表の場合、結果は最高で2ケタなので”%3d”で結果が揃います。
3桁揃えの出力結果
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
入力値nに対しては、「nの2乗の桁数 +1」をフィールドの桁数にすると表が揃います。書式文字列は以下のようにString型変数に格納して使います。以下のソースでmaxは「入力値+8」です。
書式文字列の生成
int lengthOffield = String.valueOf(max * max).length() + 1;
String format = "%" + lengthOffield + "d";
以下はソースと実行結果です。
ソース
package bigIntegerTest;
import java.util.Scanner;
public class HelloMatrixInt {
public static void main(String[] args) {
System.out.println("自然数を入力してください。");
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
scanner.close();
int max = num + 8;
int lengthOffield = String.valueOf(max * max).length() + 1;
String format = "%" + lengthOffield + "d";
for (int i = num; i <= max; i++) {
for (int j = num; j <=max; j++) {
System.out.printf(format, i*j);
}
System.out.println();
}
}
}
結果(入力値:25)
自然数を入力してください。
25
625 650 675 700 725 750 775 800 825
650 676 702 728 754 780 806 832 858
675 702 729 756 783 810 837 864 891
700 728 756 784 812 840 868 896 924
725 754 783 812 841 870 899 928 957
750 780 810 840 870 900 930 960 990
775 806 837 868 899 930 961 992 1023
800 832 864 896 928 960 992 1024 1056
825 858 891 924 957 990 1023 1056 1089
さて、上記プログラムはint型で計算しています。そのため計算結果の範囲に限界があります。int型は2147483647が正の数の限界のようです。この値はInteger.MAX_VALUEの値です。API仕様書によると「intに設定可能な最大値2^31-1を保持する定数」です。計算結果がこの値を超えるとオーバーフローします。例えば、入力値46333の場合、最後でオーバーフローします。
結果(入力値:46333)
自然数を入力してください。
46333
2146746889 2146793222 2146839555 2146885888 2146932221 2146978554 2147024887 2147071220 2147117553
2146793222 2146839556 2146885890 2146932224 2146978558 2147024892 2147071226 2147117560 2147163894
2146839555 2146885890 2146932225 2146978560 2147024895 2147071230 2147117565 2147163900 2147210235
2146885888 2146932224 2146978560 2147024896 2147071232 2147117568 2147163904 2147210240 2147256576
2146932221 2146978558 2147024895 2147071232 2147117569 2147163906 2147210243 2147256580 2147302917
2146978554 2147024892 2147071230 2147117568 2147163906 2147210244 2147256582 2147302920 2147349258
2147024887 2147071226 2147117565 2147163904 2147210243 2147256582 2147302921 2147349260 2147395599
2147071220 2147117560 2147163900 2147210240 2147256580 2147302920 2147349260 2147395600 2147441940
2147117553 2147163894 2147210235 2147256576 2147302917 2147349258 2147395599 2147441940 -2147479015
46333×46333は2147488281になりオーバーフローします。
BigIntegerを使う
この不具合をなくすためBigIntegerを使いました。46333のみに限定するならば、long型にしても良かったのですが、それでは結局数値の範囲が限定されます。BigIntegerは任意精度の数値を扱えます。
以下はソースと実行結果です。
ソース
package bigIntegerTest;
import java.math.BigInteger;
import java.util.Scanner;
public class HelloMatrixBigInteger {
public static void main(String[] args) {
System.out.println("自然数を入力してください。");
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
scanner.close();
int max = num + 8;
int lengthOffield = new BigInteger(String.valueOf(max)).multiply(new BigInteger(String.valueOf(max))).toString().length() + 1;
String format = "%" + lengthOffield + "d";
for (int i = num; i <= max; i++) {
for (int j = num; j <=max; j++) {
System.out.printf(format, new BigInteger(String.valueOf(i)).multiply(new BigInteger(String.valueOf(j))));
}
System.out.println();
}
}
}
結果(入力値:46333)
自然数を入力してください。
46333
2146746889 2146793222 2146839555 2146885888 2146932221 2146978554 2147024887 2147071220 2147117553
2146793222 2146839556 2146885890 2146932224 2146978558 2147024892 2147071226 2147117560 2147163894
2146839555 2146885890 2146932225 2146978560 2147024895 2147071230 2147117565 2147163900 2147210235
2146885888 2146932224 2146978560 2147024896 2147071232 2147117568 2147163904 2147210240 2147256576
2146932221 2146978558 2147024895 2147071232 2147117569 2147163906 2147210243 2147256580 2147302917
2146978554 2147024892 2147071230 2147117568 2147163906 2147210244 2147256582 2147302920 2147349258
2147024887 2147071226 2147117565 2147163904 2147210243 2147256582 2147302921 2147349260 2147395599
2147071220 2147117560 2147163900 2147210240 2147256580 2147302920 2147349260 2147395600 2147441940
2147117553 2147163894 2147210235 2147256576 2147302917 2147349258 2147395599 2147441940 2147488281
BigIntegerは任意精度の整数を扱うクラスです。掛け算は「BigInteger multiply(BigInteger val)」で実行できます。int型では出力できなかった「2147488281」が最後に出力されています。