0Pricing
Java Academy · レッスン

整数演算とオーバーフロー

整数の除算、剰余、オーバーフローの動作と、その検出方法を理解します。

「整数演算とオーバーフロー」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。

整数演算とオーバーフロー

Javaの整数には固定サイズがあります。計算結果が最大値または最小値を超えると、静かにラップアラウンドします。例外はスローされません。この仕組みを理解すると、見つけにくいバグを防げます。

整数の範囲

各整数型の範囲は、ビット幅によって決まります:

  • byte:-128~127
  • short:-32,768~32,767
  • int:-2,147,483,648~2,147,483,647
  • long:-9.2 × 10^18~9.2 × 10^18
System.out.println(Integer.MAX_VALUE); // 2147483647
System.out.println(Integer.MIN_VALUE); // -2147483648
System.out.println(Long.MAX_VALUE);    // 9223372036854775807
System.out.println(Byte.MAX_VALUE);    // 127

オーバーフロー:静かなラップアラウンド

Integer.MAX_VALUEに1を加えると、Integer.MIN_VALUEにラップアラウンドします。これは2の補数演算です。Javaはオーバーフローを検出する保証をせず、例外もスローしません。

int max = Integer.MAX_VALUE;
System.out.println(max + 1); // -2147483648 (overflow!)

byte b = 127;
b++;  // wraps to -128
System.out.println(b); // -128

// Real bug: counting votes in a large election with int
int votes = Integer.MAX_VALUE;
votes += 100; // silently wrong
System.out.println(votes); // negative number!

Math.addExactによるオーバーフローの検出

Java 8以降では、Math.addExact()、multiplyExact()、subtractExact()が導入されました。これらは暗黙にラップアラウンドする代わりに、オーバーフロー時にArithmeticExceptionをスローします。

try {
    int result = Math.addExact(Integer.MAX_VALUE, 1);
} catch (ArithmeticException e) {
    System.out.println("Overflow detected!"); // prints this
}

try {
    long safe = Math.multiplyExact(100_000L, 100_000L);
    System.out.println(safe); // 10000000000
} catch (ArithmeticException e) {
    System.out.println("Multiply overflow");
}

整数除算と剰余

整数除算はゼロ方向に切り捨てられます。%演算子は、被除数と同じ符号の余りを返します。ゼロ除算には注意してください。ArithmeticExceptionがスローされます。

System.out.println(10 / 3);    // 3 (not 3.33)
System.out.println(10 % 3);    // 1
System.out.println(-10 % 3);   // -1 (sign follows dividend)
System.out.println(-10 % -3);  // -1

try {
    int x = 5 / 0; // ArithmeticException: / by zero
} catch (ArithmeticException e) {
    System.out.println(e.getMessage()); // / by zero
}

// Float division by zero gives Infinity, not exception
System.out.println(5.0 / 0); // Infinity

大きな数のためのlong演算

値がintの範囲を超える可能性がある場合は、longを使用します。代入前のオーバーフローを防ぐため、longリテラルには必ずLを付けてください。

// Bug: multiplication done as int, then widened
long wrong = 1_000_000 * 1_000_000;   // overflows int!
System.out.println(wrong); // -727379968 (wrong!)

// Fix: one operand is long
long correct = 1_000_000L * 1_000_000L;
System.out.println(correct); // 1000000000000

// Or cast first
long alsOk = (long) 1_000_000 * 1_000_000;
System.out.println(alsOk); // 1000000000000

ビットシフト演算子

ビットシフト演算子は、2の累乗による乗算や除算を高速に行う方法です:

  • n << k — 左シフト:2^kを掛けます
  • n >> k — 符号付き右シフト:2^kで割ります
  • n >>> k — 符号なし右シフト:0で埋めます
int n = 8;
System.out.println(n << 1);  // 16 (8 * 2)
System.out.println(n << 2);  // 32 (8 * 4)
System.out.println(n >> 1);  // 4  (8 / 2)
System.out.println(n >> 2);  // 2  (8 / 4)

// Check if number is power of 2
boolean isPow2 = n > 0 && (n & (n - 1)) == 0;
System.out.println(isPow2); // true

ビット単位のAND、OR、XOR

ビット単位の演算子は個々のビットに対して動作し、権限、フラグ、低レベルプロトコルで使用されます。

int a = 0b1010; // 10
int b = 0b1100; // 12

System.out.println(Integer.toBinaryString(a & b)); // 1000 (AND = 8)
System.out.println(Integer.toBinaryString(a | b)); // 1110 (OR  = 14)
System.out.println(Integer.toBinaryString(a ^ b)); // 0110 (XOR = 6)
System.out.println(Integer.toBinaryString(~a));    // ...11110101 (NOT)

// Permission flags example
int READ  = 0b001;
int WRITE = 0b010;
int EXEC  = 0b100;
int perms = READ | WRITE; // user has read+write
System.out.println((perms & EXEC) != 0); // false — no exec

数値リテラル内のアンダースコア

Java 7以降では、読みやすさを向上させるために数値リテラル内でアンダースコアを使用できます。アンダースコアはコンパイラーによって無視されます。

int million = 1_000_000;
long creditCard = 4_111_1111_1111_1111L;
double pi = 3.141_592_653_589_793;
int hex = 0xFF_EC_D1_2E;
int binary = 0b0001_0101_0110;

System.out.println(million);   // 1000000
System.out.println(creditCard); // 4111111111111111

任意精度のBigInteger

値がlongの範囲を超える場合は、BigIntegerを使用します。オーバーフローは発生しませんが、プリミティブ型より低速です。暗号鍵、階乗、天文学的な大きさの数値などに使用します。

import java.math.BigInteger;

BigInteger factorial100 = BigInteger.ONE;
for (int i = 2; i <= 100; i++) {
    factorial100 = factorial100.multiply(BigInteger.valueOf(i));
}
System.out.println(factorial100.toString().length() + " digits"); // 158 digits

BigInteger a = new BigInteger("999999999999999999999999999999");
BigInteger b = new BigInteger("1");
System.out.println(a.add(b)); // 1000000000000000000000000000000

実践:オーバーフローに対応したカウンター

Math.addExactを使用し、オーバーフローが発生した場合はLong.MAX_VALUEにフォールバックする、安全にオーバーフローを処理するカウンターの実装パターンです。

class SafeCounter {
    private long count = 0;

    public void increment() {
        try {
            count = Math.addExact(count, 1L);
        } catch (ArithmeticException e) {
            count = Long.MAX_VALUE; // cap at max
        }
    }

    public long get() { return count; }
}

SafeCounter sc = new SafeCounter();
sc.increment();
sc.increment();
System.out.println(sc.get()); // 2

クイックチェック

次の式の値はいくつになりますか。

long result = 1_000_000 * 1_000_000;
System.out.println(result);

まとめ:整数演算とオーバーフロー

重要なポイント:

  • 整数オーバーフローは暗黙にラップアラウンドし、デフォルトでは例外が発生しません
  • Math.addExact/multiplyExact/subtractExactを使用してオーバーフローを検出します
  • 整数除算はゼロ方向に切り捨てられ、%の符号は被除数に従います
  • 中間結果がintの範囲を超える可能性がある場合は、longリテラル(Lサフィックス)を使用します
  • BigIntegerを使用すると、オーバーフローなしで任意の大きさの値を扱えます
  • ビットシフト演算子は、2のべき乗による乗算や除算の高速な代替手段です

よくある質問

「整数演算とオーバーフロー」レッスンは無料ですか?

はい。「整数演算とオーバーフロー」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。

「整数演算とオーバーフロー」で何を学びますか?

整数の除算、剰余、オーバーフローの動作と、その検出方法を理解します。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Java Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「整数演算とオーバーフロー」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このJava Academyレッスンでコードを書いて実行できますか?

はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Math クラスの基本
  2. 整数演算とオーバーフロー
  3. 金額計算のための BigDecimal
  4. NumberFormat と printf
← Java Academyに戻る