「整数リテラル」を学ぶうえで初心者がつまずきやすい、間違いやすいポイント集、オーバーフローの実験プログラムを解説します。
① 間違いやすいポイント集(整数リテラル編)
| No | ミスの内容 | 例 | 結果・問題点 | 正しい書き方/理解 |
|---|
| 1 | 先頭に 0 を付けてしまう | int x = 010; | 8進数として扱われる → 値は「8」になる | 普通の数値は先頭に 0 を付けない |
| 2 | 文字列と整数を混同する | "10" + 5 | 「15」ではなく "105"(文字列結合)になる | 計算したいなら "10" ではなく 10 |
| 3 | long を書くとき L を忘れる | long x = 3000000000; | コンパイルエラー(int の範囲外) | long x = 3000000000L; と書く |
| 4 | 小文字 l を使って見づらい | long x = 1234567890l; | 「1」と「l」が似ていて誤読される | 大文字 L を使う(1234567890L) |
| 5 | アンダースコアの位置ミス | int a = _1000; や int b = 1000_; | コンパイルエラー | int a = 1_000; はOK。桁の途中のみ可 |
| 6 | int の範囲を超える値 | int big = 3000000000; | コンパイルエラー(範囲外) | long big = 3000000000L; にする |
| 7 | 16進数の理解不足 | 0xA は何? | 「A」は10進の10 | 0x は16進、A〜F = 10〜15 |
| 8 | オーバーフローに気づかない | 2147483647 + 1 | -2147483648 になる | Java は自動的に循環(ラップ)する |
| 9 | 区切り文字の影響を誤解 | int n = 1_0_0; | 実はOK(100) | _ は値に影響しない |
| 10 | 変数の型を意識していない | byte b = 128; | コンパイルエラー(byte は -128~127) | 型ごとの範囲を覚える |
② オーバーフローを体験する実験プログラム
このプログラムをそのままコピーして実行すると、
「整数が最大値・最小値を超えたときどうなるか」が確認できます。
OverflowTest.java
public class OverflowTest {
public static void main(String[] args) {
// int型の最大値・最小値を確認
int max = Integer.MAX_VALUE;
int min = Integer.MIN_VALUE;
System.out.println("int の最大値: " + max);
System.out.println("int の最小値: " + min);
System.out.println("------------------------------");
// 最大値に1を足してみる
int overflow = max + 1;
System.out.println("max + 1 = " + overflow); // どうなる?
// 最小値から1を引いてみる
int underflow = min - 1;
System.out.println("min - 1 = " + underflow); // どうなる?
System.out.println("------------------------------");
// long型ではどうなるか?
long big = 9_223_372_036_854_775_807L; // longの最大値
System.out.println("long の最大値: " + big);
System.out.println("long + 1 = " + (big + 1)); // これもオーバーフロー
System.out.println("------------------------------");
// 実験:int同士の計算でも結果はintになる
int a = 1000000;
int b = 1000000;
int result = a * b;
System.out.println("1000000 * 1000000 = " + result);
// 本当は 1兆(1,000,000,000,000)になるはず
// でも int の範囲を超えるので値が狂う
System.out.println("------------------------------");
// 対策:long型を使って計算
long safeResult = (long)a * b;
System.out.println("(long)a * b = " + safeResult);
}
}
Java
実行結果(例)
int の最大値: 2147483647
int の最小値: -2147483648
------------------------------
max + 1 = -2147483648
min - 1 = 2147483647
------------------------------
long の最大値: 9223372036854775807
long + 1 = -9223372036854775808
------------------------------
1000000 * 1000000 = -727379968
------------------------------
(long)a * b = 1000000000000
結果の解説
| 行 | 内容 | 説明 |
|---|
max + 1 = -2147483648 | int の最大値を超えると、最小値に「巻き戻る」 | これが オーバーフロー |
min - 1 = 2147483647 | 最小値を下回ると、最大値に「巻き戻る」 | アンダーフロー と呼ばれる |
long + 1 | long でも同様に循環する(ただし範囲が広い) | -9,223,372,036,854,775,808 に戻る |
1000000 * 1000000 | int の範囲を超えるため誤った値になる | Java は自動的に丸めず「壊れる」 |
(long)a * b | long にキャストすれば正しい結果が出る | 型の範囲を意識することが大切 |
まとめ:オーバーフロー対策の基本
| 状況 | 問題 | 対策 |
|---|
| int の範囲を超える値を使う | 計算結果が壊れる | long にする or BigInteger を使う |
| 繰り返しカウンタが回りすぎる | 無限ループになることも | 型と初期値を確認する |
| 文字列との加算を誤用 | 思わぬ文字列連結 | " " と 数値 の違いを意識する |