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。

選擇能保留原意的處理方式。零不允許時,請驗證浮點數輸入;後續計算要求有限值時,請檢查結果是否為非有限值。三元運算子能簡潔地指定替代結果,但使用該結果的程式碼必須清楚知道它代表什麼。