← Debugging Guides

阅读中文版本

Java ArithmeticException: / by zero — Integer Division Trap

Fix "/ by zero" ArithmeticException by guarding integer divisors, distinguishing integer from floating-point division, and handling empty aggregates.

beginnerdebuggingjavaarithmeticdivision

Symptoms

  • java.lang.ArithmeticException: / by zero
  • The same expression with doubles returns Infinity instead of throwing
  • Average or percentage functions fail on empty input

Possible causes

  • Integer division or remainder uses a divisor that can be zero
  • An average is computed over an empty collection whose size is zero
  • Integer modulo by a variable that is zero on some path

Diagnosis steps

Reproduce the integer division

jshell -q <<'EOF'
try { int r = 10 / 0; } catch (ArithmeticException e) { System.out.println(e); }
EOF

Interpretation

Integer division throws; double division of 10.0/0 yields Infinity, proving the type matters.

Check the divisor at the call site

grep -rn "/ [a-zA-Z].*size()\|% .*count" src/main/java

Interpretation

Auditing divisors that come from sizes or counts finds the unguarded path.

Root cause

Integer division and remainder by zero are undefined and throw ArithmeticException. Floating-point division by zero instead yields NaN or Infinity per IEEE 754, so the bug is specific to integral arithmetic.

Fix

Guard the divisor before dividing, return a defined sentinel for empty aggregates, and choose double deliberately when Infinity or NaN semantics are acceptable.

Risk note

Returning 0 for an undefined average can be misread; return OptionalDouble.empty() to signal absence.

Verify the fix

Rerun with a zero divisor and confirm no exception and the expected sentinel; add tests for zero and nonzero divisors.

Symptoms

This guide profiles the failure behind “Java ArithmeticException: / by zero — Integer Division Trap”. It walks through the observable symptoms, a reproducible diagnosis path, the underlying root cause, the concrete fix, and how to verify the change and prevent a regression.

Observed symptoms include:

  • java.lang.ArithmeticException: / by zero
  • The same expression with doubles returns Infinity instead of throwing
  • Average or percentage functions fail on empty input

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: Reproduce the integer division

jshell -q <<'EOF'
try { int r = 10 / 0; } catch (ArithmeticException e) { System.out.println(e); }
EOF

Integer division throws; double division of 10.0/0 yields Infinity, proving the type matters.

Step 2: Check the divisor at the call site

grep -rn "/ [a-zA-Z].*size()\|% .*count" src/main/java

Auditing divisors that come from sizes or counts finds the unguarded path.

Likely contributors, in order of frequency:

  • Integer division or remainder uses a divisor that can be zero
  • An average is computed over an empty collection whose size is zero
  • Integer modulo by a variable that is zero on some path

Root Cause

Integer division and remainder by zero are undefined and throw ArithmeticException. Floating-point division by zero instead yields NaN or Infinity per IEEE 754, so the bug is specific to integral arithmetic.

The Fix

Guard the divisor before dividing, return a defined sentinel for empty aggregates, and choose double deliberately when Infinity or NaN semantics are acceptable.

Watch out: Returning 0 for an undefined average can be misread; return OptionalDouble.empty() to signal absence.

public static OptionalDouble average(int[] values) {
    if (values.length == 0) return OptionalDouble.empty(); // no division
    long sum = 0;
    for (int v : values) sum += v;
    return OptionalDouble.of((double) sum / values.length);
}

int divisor = 0;
int safe = divisor == 0 ? 0 : 100 / divisor; // guarded

Verify and Prevent

Rerun with a zero divisor and confirm no exception and the expected sentinel; add tests for zero and nonzero divisors.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.