除法看似簡單,實則暗藏陷阱。整數除以零拋異常、浮點數除以零得無窮大、NaN 自不相等、精度溢位……不知這些特性,代碼極易在邊界條件下失效。本文系統梳理 Java 除法與求餘的所有邊界行為,並給出安全編碼模式。
ArithmeticException(運行時異常)12/10 = 1、-12/10 = -1)float/double,整個表達式提升為浮點運算System.out.println(12/10); // 1
System.out.println(12f/10); // 1.2
System.out.println(12/10.0); // 1.2
遵循 IEEE 754 標準,除數為 0 不拋異常,而是返回特殊值:
| 運算式 | 結果 | 說明 |
|---|---|---|
| 非零 / 0.0 | Infinity | 正無窮大 |
| 非零 / -0.0 | -Infinity | 負無窮大 |
| 0.0 / 0.0 | NaN | 非數字 |
| -0.0 / 0.0 | NaN | 非數字 |
| 0.0 / 非零 | ±0.0 | 帶符號零,符號同被除數 |
Double x = 1.0 / 0.0;
x.isInfinite() // true
x == Double.POSITIVE_INFINITY // true
Double y = 0.0 / 0.0;
y.isNaN() // true
y == Double.NaN // false!NaN != NaN
Double.isNaN(y) // true 靜態方法正確
陷阱:NaN != NaN,必須用 isNaN() 或 Double.isNaN() 判斷。
POSITIVE_INFINITY = 1.0 / 0.0;
NEGATIVE_INFINITY = -1.0 / 0.0;
NaN = 0.0 / 0.0;
a % b 符號同被除數 a(23%-4 = 3、-23%4 = -3)NaN23 % 4 // 3
23 % -4 // 3
-23 % 4 // -3
23.0 % 0.0 // NaN
0.0 % 0.0 // NaN
public static double safeDiv(double dividend, double divisor, double defaultValue) {
if (divisor == 0) return defaultValue;
double result = dividend / divisor;
if (Double.isInfinite(result) || Double.isNaN(result)) return defaultValue;
return result;
}
財務/精度敏感場景
嚴禁使用 float/double,改用 BigDecimal:
BigDecimal a = new BigDecimal("1.2");
BigDecimal b = new BigDecimal("0.1");
BigDecimal result = a.divide(b, RoundingMode.HALF_UP); // 12
總結檢核表
- ✅ 整數除法檢查除數非零
- ✅ 浮點除法結果必檢
isInfinite()/isNaN()
- ✅
NaN 比較只用 isNaN()
- ✅ 金額計算用
BigDecimal
- ✅ 求餘符號取決於被除數
掌握這些細節,讓數值計算代碼經得起邊界測試與生產考驗。