【Java】桁溢れ(オーバーフロー)の検証


生徒さんから質問があったので桁溢れ(オーバーフロー)について説明します。

きっかけは以下のプログラムです。

public class OverflowSample {
	public static void main(String[] args) {
		int i = 1;

		for (; i >= 0; i++) {

		}
		System.out.println(i);
	}
}

こちらの実行結果はどうなるでしょう?
実は-2147483648と出力されます。
条件が0 >= iとなっているのにも関わらず、無限ループではなく実行できます。
しかも0からインクリメントしていたはずなのに何故かiがマイナスの値になってしまいました。

この原因が桁溢れ(オーバーフロー)です。
意味は名前の通り、決められたデータ型の範囲をオーバーしてしまうことです。
例えばintは-2147483648~2147483647の整数しか格納することはできません。
範囲外の値を代入しようとするとコンパイルエラーになります。

しかし、以下のコードはコンパイルが通ります。

int i = 2147483647 + 1;

そしてこのiを出力すると-2147483648が出力されます。

では何故マイナスの値になってしまうのでしょう?

これは細かい話になるのですが、数値が内部ではビットで扱われているからです。
byteで説明しましょう。
byteは8ビットです。つまり2進数で8桁というとです。
8つの0と1の組み合わせで-128~127の計256通りの数字が表現でき、以下の対応になっています。
-128を2進数にすると10000000
-1を2進数にすると11111111
0を2進数にすると00000000
127を2進数にすると01111111

では127、つまり01111111に1をプラスするとどうなるでしょう。
一番右のビットからどんどん繰り上がって、2進数の並びは10000000となります。
この10000000の並びはjavaのbyteでは-128にあたるわけです。

また、-1、つまり11111111に1プラスすると100000000になります。
byteは8ビットなので右8桁分しか認識しません。
したがって、一番左のビットが切り捨てられ00000000、つまり0になります。

要は127の次の数は最小の-128となってグルグル回るわけですね。

ちなみにbyteの場合は以下の記述はコンパイルエラーです。

byte b = 127 + 1;

もし上記を確認したいのであればキャストを利用しましょう。

System.out.println((byte) 128); // -128と出力される
  • このエントリーをはてなブックマークに追加

PAGE TOP