pythonseverity: can-fix
ZeroDivisionError

Python ZeroDivisionError: division by zero

Division by zero

100% fixable~3 mindifficulty: beginner

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 / b

What 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.

> advertisementAdSense placeholder

How to fix it

  1. 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
  2. 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)
  3. 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.
  4. 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
  5. 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
  6. 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.

disclosure:Errordex runs AdSense, has zero third-party affiliate or sponsored links, and occasionally links to the editor’s own paid digital products (clearly labelled). Every fix is manually verified against official sources listed in the “sources” sidebar. If a fix here didn’t work for you, please email so we can update the page.