Python ZeroDivisionError: division by zero
Division by zero
Verified against Python docs: Built-in Exceptions, CPython source: Objects/floatobject.c, IEEE 754-2008 specification · Updated May 2026
> quick_fix
You divided or used % with zero. Add an explicit guard for the zero case before dividing. For floats, use math.isclose(d, 0) since 1e-300 is non-zero but division still overflows. Returning a sentinel (None, NaN) is usually cleaner than letting the error propagate.
# Guard the divisor
def safe_div(a, b):
if b == 0:
return None # or float('nan'), or raise a domain-specific error
return a / b
# For floats with possible underflow
import math
def safe_div_f(a, b):
return float('nan') if math.isclose(b, 0) else a / bWhat causes this error
Python raises ZeroDivisionError on integer or modulo division by 0 (a / 0, a // 0, a % 0). For float division, only true 0.0 raises; a tiny non-zero float succeeds and may produce inf or overflow. Common triggers: averaging an empty list, computing rates without a sample-size check, or arithmetic on user-supplied data that includes 0.
How to fix it
- 01
step 1
Find the divisor that's zero
Read the traceback. The line number tells you the division. The harder question is why it's zero. Print the divisor right before the line.
print(f'Dividing {numerator} / {denominator}') result = numerator / denominator - 02
step 2
Decide what zero should mean
There's no universal right answer. Returning None signals 'undefined'. Returning 0 means 'no rate'. Returning float('inf') matches IEEE 754. Raising a domain error like 'NoSamplesError' is most explicit. Pick one and stick with it.
def average(xs): if not xs: return 0.0 # or raise EmptyList() return sum(xs) / len(xs) - 03
step 3
Use float('nan') when computation must continue
In data pipelines, you often want NaN to flow through subsequent operations rather than crashing. Pandas and NumPy do this by default; for plain Python use float('nan').
def safe_rate(numer, denom): return numer / denom if denom else float('nan') rates = [safe_rate(c, t) for c, t in pairs] # NaN propagates through sum, mean, etc. - 04
step 4
Watch for floats that look non-zero
1e-300 is non-zero, so 1.0 / 1e-300 doesn't raise but produces inf. Use math.isclose for 'close enough to zero' tests, or wrap in try/except OverflowError.
import math x = 1e-300 if math.isclose(x, 0, abs_tol=1e-9): return None # 1.0 / 1e-300 -> inf, no exception - 05
step 5
Check NumPy/pandas separately
NumPy doesn't raise ZeroDivisionError - it produces inf or nan and emits a RuntimeWarning. pandas inherits this. If you want strict behaviour, use np.seterr(divide='raise').
import numpy as np # Default - warning, returns inf np.array([1.0]) / np.array([0.0]) # array([inf]) # Strict np.seterr(divide='raise') np.array([1.0]) / np.array([0.0]) # FloatingPointError - 06
step 6
Catch the exception only at the boundary
Don't wrap every division in try/except. Push validation up to where data enters your function (return early on empty input) so the math layer can stay simple.
def click_through_rate(clicks, impressions): # Validate at the boundary if impressions <= 0: return 0.0 return clicks / impressions
Why ZeroDivisionError happens at the runtime level
CPython's arithmetic dispatch in Objects/longobject.c (for int) and Objects/floatobject.c (for float) explicitly checks for zero divisors before delegating to the underlying C operation. For ints, the check happens in long_divmod and raises PyExc_ZeroDivisionError directly. For floats, CPython chooses to raise rather than follow IEEE 754's silent inf/nan production - this is a deliberate design choice traced back to PEP 238 discussions, valuing explicit errors over IEEE conformance. NumPy bypasses this by using its own ufunc machinery, which can be configured with seterr to either warn or raise on zero division.
Common debug mistakes for ZeroDivisionError
- Computing average over a possibly-empty collection without a length check.
- Using % to test divisibility (n % d == 0) when d itself can be zero from a config.
- Assuming float('1e-300') / 1.0 protects you from div-by-zero - it doesn't (the divisor is just very small, not zero).
- Catching ZeroDivisionError but logging the wrong values, making the bug hard to reproduce.
- Using NumPy with default seterr settings, then surprised when divide-by-zero produces inf instead of an exception.
When ZeroDivisionError signals a deeper problem
Persistent ZeroDivisionError in a domain layer signals missing input validation at the boundary. The fix is not to scatter try/except across math functions but to introduce a typed boundary: validators that reject zero divisors before they reach the math, or domain types like PositiveInt that make zero unrepresentable. For statistical code, decide upfront how 'no data' translates to outputs (NaN, None, exception) and document it. The code style should match the data: pipelines that expect missing values use NaN; APIs that promise a number raise; functions that compute a meaningful zero-default (like 'no clicks' = 0% CTR) handle it explicitly.
Frequently asked questions
Why does 1 / 0 raise but 1.0 / 0.0 also raise?
Both raise in Python, but for different reasons. 1 / 0 (int division using true division operator /) and 1 // 0 (integer floor division) both raise ZeroDivisionError because integer math has no representation for infinity. 1.0 / 0.0 also raises in CPython, even though IEEE 754 floats have +inf and -inf - this is a Python design choice, not a hardware constraint. NumPy doesn't follow this convention; np.float64(1.0) / np.float64(0.0) returns inf with a warning. If you need IEEE behaviour, use NumPy or compute manually with float('inf').
What's the difference between ZeroDivisionError and FloatingPointError?
ZeroDivisionError fires on Python's built-in arithmetic when the divisor is zero. FloatingPointError is raised by NumPy when np.seterr is set to 'raise', covering not just div-by-zero but underflow, overflow, and invalid (nan-producing) operations. They're distinct exceptions and don't share a common parent beyond Exception. If you write code that uses both pure Python and NumPy, catch both: except (ZeroDivisionError, FloatingPointError).
Should I use try/except or pre-check for zero?
Pre-check (LBYL: Look Before You Leap) when zero is a normal expected case (an empty list, a feature flag for 'don't divide'). Try/except (EAFP: Easier to Ask Forgiveness than Permission) when zero is unexpected and signals a bug or invalid input. Pythonic style favors EAFP, but for math specifically, LBYL is usually clearer because the right behaviour for zero is meaningful and shouldn't be hidden inside an except clause.
Why does 0 % 0 raise ZeroDivisionError?
Python's modulo operator is defined in terms of the equation a = (a // b) * b + (a % b). Both // and % require b != 0 to produce a meaningful result. The C standard library's fmod and Python's math.fmod also reject zero divisors. The same applies to divmod(a, 0). All three operations raise ZeroDivisionError with the message 'integer modulo by zero' or 'float modulo' depending on operand types. There is no built-in way to make 0 % 0 silently return 0; you must guard the operation explicitly.