HOWTO · Java
Java 中除以零異常
了解為什麼 Java 整數除以零會擲出 ArithmeticException,而浮點數除法遵循 IEEE 754:非零分子除以正負零會產生帶符號的 Infinity,零除以零則會產生 NaN,並學習如何安全處理這兩種情況。
本頁內容
Java 對整數與浮點數除以零採取不同處理方式。整數除法會擲出 ArithmeticException;浮點數除法遵循 IEEE 754,非零分子除以零或負零會產生帶符號的 Infinity,零除以零則會產生 NaN。除法前先檢查整數分母,並依應用程式需求決定是否拒絕浮點數零分母,或處理其產生的特殊值。
Java 中的整數除以零
對 int 和 long 等整數型別而言,除以零會擲出 ArithmeticException。整數除數為零時,餘數運算子也會有相同結果。若未捕捉例外,目前的執行流程會在除法處停止,後續陳述式不會執行。
以下是完整程式,會計算兩個整數輸入的商。
public class Main {
public static void main(String[] args) {
int numerator = 10;
int denominator = 2;
int quotient = numerator / denominator;
System.out.println("Quotient: " + quotient);
}
}
結果是整數,因此 10 / 2 會得到 5。若將 denominator 改為 0,除法會擲出 ArithmeticException,後續的列印陳述式不會執行。堆疊追蹤中的確切來源位置資訊,會依程式的編譯與執行方式而異。
使用條件判斷避免整數除以零
如果零不是這項工作的有效除數,請在執行運算前先檢查,並選擇符合應用程式需求的處理方式。以下範例使用固定值,因此可以整理成單一檔案編譯及執行;在實際應用程式中,請改用經過驗證的輸入值。
public class Main {
public static void main(String[] args) {
int numerator = 10;
int denominator = 0;
if (denominator == 0) {
System.out.println("Cannot calculate a quotient: denominator is zero.");
} else {
int quotient = numerator / denominator;
System.out.println("Quotient: " + quotient);
}
}
}
只有在分母不為零的分支中才會執行除法。處理使用者輸入時,請另外驗證解析結果,並依程式的介面回報問題,例如提示使用者重新輸入,或在使用者介面中顯示驗證訊息。
使用 try-catch 處理整數除以零
當整數除法是較大型操作的一部分,而該操作可能失敗且呼叫端有實際可行的復原方式時,使用 try-catch 區塊會很有幫助。如果能在運算附近捕捉 ArithmeticException 並採取有用的處理方式,就可以這麼做;若零是預期可能出現的輸入,通常直接先檢查會更清楚。
public class Main {
public static void main(String[] args) {
int numerator = 10;
int denominator = 0;
try {
int quotient = numerator / denominator;
System.out.println("Quotient: " + quotient);
} catch (ArithmeticException error) {
System.out.println("Cannot calculate a quotient: denominator is zero.");
}
}
}
這段程式會捕捉整數除法失敗,讓程式在 catch 區塊之後繼續執行。它是在嘗試運算後處理失敗,並不會讓除以零變成有效操作。避免使用範圍過廣的捕捉方式,以免掩蓋其他程式錯誤。
使用三元運算子處理整數除以零
三元運算式可以讓簡短的選擇靠近計算。請明確指定替代值:在某些特定領域中,回傳 0 可能合適,但也可能被誤認為是真正的商。如果呼叫端必須分辨失敗與數值結果,請使用資訊更完整的結果型別,或改用獨立的條件判斷。
public class Main {
public static void main(String[] args) {
int numerator = 10;
int denominator = 0;
String result = denominator == 0
? "No quotient: denominator is zero."
: Integer.toString(numerator / denominator);
System.out.println(result);
}
}
Java 只會計算被選中的分支,因此分母為零時會略過除法。這個範例使用訊息而非數值預設值,讓兩種結果有所區別。
Java 中的浮點數除以零
Java 的 float 和 double 除法遵循 IEEE 754。非零值除以正零或負零會產生帶符號的 Infinity;正負號取決於兩個運算元。零除以零會產生 NaN(Not a Number,非數值)。這些運算本身不會擲出 ArithmeticException。
public class Main {
public static void main(String[] args) {
double positiveInfinity = 1.0 / 0.0;
double negativeInfinity = 1.0 / -0.0;
double notANumber = 0.0 / 0.0;
System.out.println("Positive divisor sign: " + positiveInfinity);
System.out.println("Negative divisor sign: " + negativeInfinity);
System.out.println("Zero divided by zero: " + notANumber);
}
}
Infinity 和 NaN 是意義不同的值。後續計算若涉及這些值,也可能產生非有限結果。若應用程式要求數值必須有限,請使用 Double.isFinite(value) 或對應的 Float.isFinite(value) 檢查;像 value == Double.NaN 這類比較無法偵測 NaN。
使用條件判斷檢查浮點數分母
如果應用程式規定正零和負零都不能作為分母,請在除法前將值與 0.0 比較。Java 在這項比較中會將正零與負零視為相等。精確的零值檢查無法處理所有接近零時的數值穩定性問題;可接受的範圍取決於資料的尺度與意義。
public class Main {
public static void main(String[] args) {
double numerator = 10.0;
double denominator = 0.0;
if (denominator == 0.0) {
System.out.println("Cannot calculate a quotient: denominator is zero.");
} else {
double quotient = numerator / denominator;
System.out.println("Quotient: " + quotient);
}
}
}
只有在領域需求適用時才使用容許誤差,並依數值的大小與單位選擇合適的誤差。除法後,若下游處理不接受 Infinity 或 NaN,請使用 Double.isFinite 驗證結果。
為浮點數零分母擲出並捕捉應用程式自訂例外
浮點數除以零不會擲出 ArithmeticException,因此只在除法外包上 try-catch 並不能拒絕零分母。如果 API 將這種情況視為錯誤,請先明確檢查,並在除法前擲出應用程式自訂例外。範例使用 IllegalArgumentException,因為提供的引數不在方法接受的輸入範圍內。
public class Main {
static double divide(double numerator, double denominator) {
if (denominator == 0.0) {
throw new IllegalArgumentException("Denominator must not be zero.");
}
return numerator / denominator;
}
public static void main(String[] args) {
try {
System.out.println("Quotient: " + divide(10.0, 0.0));
} catch (IllegalArgumentException error) {
System.out.println("Cannot calculate a quotient: " + error.getMessage());
}
}
}
例外是由明確檢查所擲出,而不是由除法運算產生。如果零在你的領域中是有效值,就不要用這種方式拒絕它;請依應用程式需求處理產生的 Infinity 或 NaN。
使用三元運算子為浮點數零分母選擇替代結果
當替代結果對呼叫端而言很明確時,可以使用三元運算式簡潔地表達處理政策。這裡以訊息表示沒有商的情況,避免把 0.0 說成除以零在數學上的結果。
public class Main {
public static void main(String[] args) {
double numerator = 10.0;
double denominator = 0.0;
String result = denominator == 0.0
? "No quotient: denominator is zero."
: Double.toString(numerator / denominator);
System.out.println(result);
}
}
如果方法必須回傳數值,只有在領域中已定義其意義時才選擇替代值,並提供其他方式讓呼叫端辨識這個替代值。否則,請保留 IEEE 754 的結果,並在不允許非有限值的地方加以驗證。
結論
對整數除法而言,如果零除數是預期可能出現的輸入,就先檢查並防止除法;若周遭操作適合使用例外處理,也可以捕捉 ArithmeticException。對浮點數除法而言,Java 遵循 IEEE 754:非零值除以正零或負零會產生帶符號的 Infinity,零除以零則會產生 NaN。
選擇能保留原意的處理方式。零不允許時,請驗證浮點數輸入;後續計算要求有限值時,請檢查結果是否為非有限值。三元運算子能簡潔地指定替代結果,但使用該結果的程式碼必須清楚知道它代表什麼。