When does math.fmod(x, y) disagree with x % y in Python, and which should you use?
answer
- Two remainders, two sign conventions
- One follows C, one follows Python
- Which one always hands back a float?
- The docs prefer one for floats
basics
~20 sThey disagree whenever the operands have different signs: math.fmod follows C and gives the dividend's sign, while % floors and gives the divisor's sign. Use % for integers and wrap-around indexing, math.fmod for float remainders.
solid answer
~40 s`math.fmod` is a thin wrapper over C's `fmod`, which truncates the quotient toward zero, so its result carries the sign of the **dividend**: `math.fmod(-7, 2)` is `-1.0`. Python's `%` floors the quotient, so its result carries the sign of the **divisor**: `-7 % 2` is `1`. With operands of the same sign they agree in value. `math.fmod` also always converts to `float` and returns a `float`, which loses precision on integers beyond 2**53, and it raises `ValueError` for a zero divisor where `%` raises `ZeroDivisionError`. The standard-library guidance is `%` for integers, `math.fmod` for floats - it is more accurate when the operands differ wildly in magnitude - and `math.remainder` when you want the IEEE-754 remainder with the quotient rounded to nearest.
code
pycon · 11 lines>>> import math
>>> -7 % 2
1
>>> math.fmod(-7, 2)
-1.0
>>> 7 % -2
-1
>>> math.fmod(7, -2)
1.0
>>> math.remainder(7, 3)
1.0go deeper
It is enough to know that % is the everyday remainder operator and that math.fmod is a separate, C-flavoured function you should not reach for by default.
Explain the sign rule concretely - math.fmod follows the dividend, % follows the divisor - and note that math.fmod always returns a float, so integer work belongs to %.
Show judgement about float accuracy and interoperability: pick math.fmod when the inputs are floats or when mirroring truncating semantics from another language, and say so in a comment so the mismatch does not read as a bug.
Decide once, for the codebase, which remainder convention crosses a boundary shared with services or specifications written in truncating languages, and normalise at that boundary rather than sprinkling per-call corrections.
## Two remainders, two conventions Python ships two general-purpose remainder operations plus a third specialised one, and they differ in a way that matters exactly when the signs of the operands differ. `x % y` is derived from floored division. The quotient rounds toward negative infinity, so the remainder takes the sign of the **divisor**. `math.fmod(x, y)` is a thin wrapper over the C library's `fmod`, which is defined from truncated division. The quotient rounds toward zero, so the remainder takes the sign of the **dividend**. ``` -7 % 2 == 1 math.fmod(-7, 2) == -1.0 7 % -2 == -1 math.fmod(7, -2) == 1.0 7 % 2 == 1 math.fmod(7, 2) == 1.0 ``` When both operands share a sign the two agree in value (though not in type). When the signs differ they land on opposite sides, and the difference is exactly the divisor. ## Types, and why that bites `%` preserves types: two ints give an int, and anything involving a float gives a float. `math.fmod` converts **both** arguments to `float` and always returns a `float`. On small values that is harmless, but Python's ints are unbounded and binary64 floats are not: past 2**53 the conversion is lossy, so `math.fmod` on very large integers can return an answer that is simply wrong for the integers you passed, while `%` stays exact for integers of any size. For integer work, `%` is not merely idiomatic - it is the only correct choice. The zero divisor differs too. `x % 0` raises `ZeroDivisionError`. `math.fmod(x, 0)` follows the C convention of a domain error and raises `ValueError`. Code that catches one will not catch the other. ## Why fmod exists at all If `%` is the Pythonic operator, why keep the C one? Two reasons, and knowing them is what separates a recited answer from an understood one. The first is **accuracy on floats**. `%` on floats derives the remainder from a computed floored quotient, and both steps round. When `x` is enormous relative to `y` the error can be a large fraction of `y`, and in bad cases the sign convention can even come out surprising. `math.fmod` is specified to be exact - the C library computes the truncated remainder without an intermediate rounded quotient - so for float inputs the standard library explicitly recommends it. The rule of thumb: `%` for integers, `math.fmod` for floats. The second is **interoperability**. When you are reproducing a formula from a C, Java or hardware specification, or matching the output of a peer service written in one of those languages, you want the truncating convention. Using `math.fmod` says that intent in the code, instead of hand-rolling a sign correction that a later reader will misread as a bug. ## The third one: math.remainder `math.remainder(x, y)` implements the IEEE-754 remainder operation, which is neither of the above: the quotient is rounded to the **nearest** integer, ties to even, so the result always lies in the closed interval from `-abs(y)/2` to `abs(y)/2`. `math.remainder(7, 3)` is `1.0`, but `math.remainder(7, 2)` is `-1.0`, because 3.5 rounds to the even 4. That makes it the right tool for argument reduction in numerical code - normalising an angle to the smallest-magnitude equivalent, for instance - and the wrong tool for anything that expects a remainder in `range(y)`. It was added in Python 3.7. ## Choosing, in one paragraph Use `%` for integers, always, and for the wrap-around arithmetic that flooring makes correct by construction - ring buffers, calendar shifts, hashing into buckets. Use `math.fmod` when the operands are floats and you want the accurate remainder, or when you are deliberately matching truncating semantics from another language. Use `math.remainder` when you want the signed value closest to zero. And when you write the choice down, leave a comment naming the convention, because the next reader will otherwise assume the mismatch with `%` is an accident.
- Why does the standard library recommend math.fmod for floats but % for integers?For floats, `%` derives the remainder from a computed floored quotient and both steps round, so when the operands differ greatly in magnitude the error can be a large fraction of the divisor; `math.fmod` is computed exactly by the C library. For integers the reverse holds: `math.fmod` converts to binary64 and loses precision past 2**53, while `%` is exact for Python ints of any size.
- How does math.remainder differ from both math.fmod and %?It implements the IEEE-754 remainder: the quotient is rounded to the nearest integer with ties to even rather than floored or truncated, so the result is the signed value closest to zero, always within half the divisor's magnitude. `math.remainder(7, 2)` is `-1.0` because 3.5 rounds to 4. That suits argument reduction such as normalising an angle, and is wrong wherever you expect a remainder inside `range(y)`.
saying these in an interview costs you the question
- Says math.fmod and % are interchangeable
- Thinks math.fmod returns an int for int arguments
- Uses math.fmod on very large integers and expects exactness
- Expects math.fmod(x, 0) to raise ZeroDivisionError
- Assumes math.remainder is just a spelling of %