ArithmeticException の全体像
ArithmeticException は「算術計算が不正で続行できない」ときに投げられる実行時例外です。代表例は整数の 0 除算(割り算・剰余の分母が 0)。浮動小数点(double/float)の 0 除算は例外にならず、Infinity や NaN が返る点が重要な違いです。BigDecimal などの高精度計算でも、条件次第で ArithmeticException が発生します。
どんなときに発生するか
整数の 0 除算(割り算・剰余)
int a = 10;
int b = 0;
// int c = a / b; // ArithmeticException: / by zero
// int r = a % b; // ArithmeticException: / by zero
Javaint/long の割り算・剰余は分母が 0 だと例外。try-catch で捕まえられますが、通常は事前に 0 チェックで防ぎます。
浮動小数点の 0 除算は例外にならない
double x = 1.0;
double y = 0.0;
System.out.println(x / y); // Infinity(例外なし)
System.out.println(y / y); // NaN(例外なし)
Javadouble/float は IEEE 754 に従い、例外ではなく特殊値を返します。数値が Infinity/NaN になって以降の計算も壊れやすく、明示的な検査が必要です。
BigDecimal の「丸め無し割り算」
import java.math.*;
BigDecimal p = new BigDecimal("1");
BigDecimal q = new BigDecimal("3");
// BigDecimal r = p.divide(q); // ArithmeticException: 非終端小数のため丸めが必要
BigDecimal r2 = p.divide(q, 10, RoundingMode.HALF_UP); // 10桁に丸めて安全
Java割り算結果が有限小数にならないとき、丸め指定なしの divide は例外になります。必ず scale(桁数)と RoundingMode を指定しましょう。
BigInteger の 0 除算
import java.math.BigInteger;
BigInteger a = BigInteger.TEN;
BigInteger z = BigInteger.ZERO;
// a.divide(z); // ArithmeticException: Division by zero
Java任意精度整数でも分母 0 は例外です。
オーバーフロー検知系のメソッド
int a = Integer.MAX_VALUE;
int b = 1;
// a + b; // オーバーフローするが「例外は出ない」
Math.addExact(a, b); // ArithmeticException: integer overflow
Java通常の int/long 演算はオーバーフローしても例外になりません(値が循環)。確実に検知したいときは Math.addExact/subtractExact/multiplyExact を使います。
重要ポイントの深掘り:例外にならない「危険な状態」
「オーバーフローは黙って起きる」
int/long の加算・乗算は上限を超えると勝手に値が回り込み、誤結果になります。安全性が必要な場面では Exact 系メソッドか、BigInteger/BigDecimal を使う発想が有効です。
Infinity/NaN を放置しない
double/float では 0 除算や未定義演算で Infinity/NaN が返ります。以降の計算は伝播して結果が無意味になるため、節目でチェックします。
double v = 1.0 / 0.0; // Infinity
if (Double.isInfinite(v) || Double.isNaN(v)) {
// ここで補正・ログ・フォールバック
}
Java予防と安全な書き方
0 チェックで前倒し検証
static int safeDivide(int a, int b) {
if (b == 0) throw new IllegalArgumentException("divisor must not be 0");
return a / b;
}
Java例外を try-catch に頼るより、契約違反を入口で弾いて明確化するほうが読みやすく安全です。
BigDecimal は必ず丸め指定
import java.math.BigDecimal;
import java.math.RoundingMode;
static BigDecimal ratio(BigDecimal num, BigDecimal den) {
if (den.compareTo(BigDecimal.ZERO) == 0)
throw new IllegalArgumentException("denominator must not be 0");
return num.divide(den, 8, RoundingMode.HALF_UP); // 8桁で丸め
}
Java丸めと桁数の方針を定数化して全体で統一すると、ぶれなくなります。
オーバーフローを検知する
static int safeAdd(int a, int b) {
return Math.addExact(a, b); // 溢れたら ArithmeticException
}
Java金融やカウンタの上限管理など、誤結果が許されない場面で有効です。
例題で身につける
例 1: 整数割り算の安全ラッパー
public class IntDiv {
public static int div(int a, int b) {
if (b == 0) throw new IllegalArgumentException("divisor must not be 0");
return a / b;
}
public static void main(String[] args) {
System.out.println(div(10, 2)); // 5
System.out.println(div(10, 0)); // IllegalArgumentException
}
}
Java例 2: BigDecimal 割り算の丸め方針を固定
import java.math.*;
public class Ratios {
private static final int SCALE = 6;
private static final RoundingMode MODE = RoundingMode.HALF_UP;
static BigDecimal percent(BigDecimal part, BigDecimal total) {
if (total.compareTo(BigDecimal.ZERO) == 0) return BigDecimal.ZERO;
return part.multiply(BigDecimal.valueOf(100))
.divide(total, SCALE, MODE);
}
public static void main(String[] args) {
System.out.println(percent(new BigDecimal("1"), new BigDecimal("3"))); // 33.333333
}
}
Java例 3: 浮動小数点の特殊値チェック
public class FPGuard {
static double safeDiv(double a, double b) {
double r = a / b; // 0除算でも例外にならない
if (Double.isInfinite(r) || Double.isNaN(r)) throw new ArithmeticException("invalid FP result");
return r;
}
public static void main(String[] args) {
System.out.println(safeDiv(1.0, 2.0)); // 0.5
System.out.println(safeDiv(1.0, 0.0)); // ArithmeticException
}
}
Java例 4: オーバーフローを検知するカウンタ
public class Counter {
private int value = 0;
public void add(int delta) {
value = Math.addExact(value, delta); // 溢れたら即例外
}
public int get() { return value; }
}
Java仕上げのアドバイス(重要部分のまとめ)
ArithmeticException の主因は「整数の 0 除算」と「高精度演算の丸め未指定」です。0 チェックを前倒しにして契約違反を弾く、BigDecimal は必ず桁数と丸めを指定、浮動小数点は例外にならないので Infinity/NaN を検知、整数オーバーフローは黙って起きるため Exact 系メソッドや BigInteger を使う——これで算術由来の不具合は大幅に減ります。
