Code Fix

中級

ArithmeticException: / by zero の原因と直し方

int型同士の割り算・剰余算で分母が0だと例外になります。doubleとの挙動の違いと、事前チェックの書き方を扱います。

エラーメッセージの読み方

Exception in thread "main" java.lang.ArithmeticException: / by zero
main
スレッド名 — mainなら起動直後の処理で発生しています
java.lang
パッケージ — java.lang なら標準の基本例外です
ArithmeticException
例外クラス — 何が起きたか。ここを検索するのが最短です
/ by zero
詳細メッセージ — どの値が問題だったか

このエラーが出る典型パターン

パターン1

 1  public class Main {
 2      public static void main(String[] args) {
 3          int total = 10;
 4          int groups = 0 ;
                          ^
 5          System.out.println(total / groups);
 6      }
 7  }
Exception in thread "main" java.lang.ArithmeticException: / by zeroexited with code 1

整数の0除算は例外になります。doubleの場合は例外ではなくInfinityになる点が違います。

直し方: 0 を 5 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  public class Main {
 2      public static void main(String[] args) {
 3          int score = 87;
 4          int bucket = 0 ;
                          ^
 5          System.out.println(score % bucket);
 6      }
 7  }
Exception in thread "main" java.lang.ArithmeticException: / by zeroexited with code 1

剰余演算子(%)で0除算をしても、メッセージは / by zero のまま同じ例外が投げられます。/だけの問題ではありません。

直し方: 0 を 10 にします。

この問題を解いてみる →

パターン3

 1  public class Main {
 2      public static void main(String[] args) {
 3          int score = 10;
 4          double denom = 0;
               ^
 5          try {
 6              System.out.println(score / denom);
 7          } catch (ArithmeticException e) {
 8              System.out.println("caught");
 9          }
10      }
11  }
出力: Infinity期待: caught (コンパイルは通っています)

分母がdouble型だと0除算は例外にならずInfinityになるため、catchブロックが実行されません。

直し方: double を int にします。

この問題を解いてみる →

パターン4

 1  public class Main {
 2      public static void main(String[] args) {
 3          int a = 10;
 4          int b = 0 ;
                     ^
 5          System.out.println(Math.floorDiv(a, b));
 6      }
 7  }
Exception in thread "main" java.lang.ArithmeticException: / by zeroexited with code 1

Math.floorDivも内部で整数除算を行うため、分母が0だと同じ例外になります。

直し方: 0 を 2 にします。

この問題を解いてみる →

パターン5

 1  public class Main {
 2      public static void main(String[] args) {
 3          int[] scores = {}       ;
                               ^
 4          int sum = 0;
 5          for (int s : scores) sum += s;
 6          System.out.println(sum / scores.length);
 7      }
 8  }
Exception in thread "main" java.lang.ArithmeticException: / by zeroexited with code 1

配列が空だとlengthが0になり、平均を求める割り算がそのまま0除算になります。

直し方: {} を {1, 2, 3} にします。

この問題を解いてみる →

よくある誤解

0で割ると自動的に0やInfinityになると思われがちですが、int型同士の場合はArithmeticExceptionが投げられて処理が止まります。doubleの場合は例外にならずInfinityやNaNになる点が違います。

実務での勘所

doubleの0除算が例外にならないのは、Java独自の判断ではなくIEEE 754という浮動小数点の国際規格がそう定めているためです。この規格ではn / 0.0はInfinityに、0.0 / 0.0はNaN(Not a Number)になると決まっており、Javaに限らずこの規格に準拠するほとんどの言語で同じ結果になります。NaNにはNaN == NaNがfalseになるという特殊な性質もあり、0除算の結果を安全のつもりで比較チェックすると、意図通りに動かないことがあります。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)