java-beginner.com ブログ

プログラミングを学習するブログ(Javaをメインに)

掛け算の表でBigIntegerを使う

投稿日:

最終更新日:2016年08月01日

アイキャッチ

こんにちは。「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」が最後に出力されています。