What do -7 // 2 and -7 % 2 evaluate to in Python, and why?
answer
- Think about which way rounding goes
- Not truncation toward zero
- Floor of the exact quotient
- Ask which operand fixes the sign
basics
~20 s-7 // 2 is -4 and -7 % 2 is 1. Python floors the quotient toward negative infinity instead of truncating toward zero, so the remainder always carries the sign of the divisor rather than the dividend.
solid answer
~50 sPython defines `//` as **floored** division: the result is the largest integer not greater than the exact quotient. The exact quotient of -7 and 2 is -3.5, and the floor of -3.5 is -4, so `-7 // 2` is -4. The `%` operator is then derived from that choice so that `a == (a // b) * b + a % b` holds, which forces `-7 % 2` to be `-7 - (-4 * 2)`, that is 1. The practical rule is that the remainder takes the sign of the **divisor**: `7 % -2` is -1, while `-7 % 2` is 1. C, Java, Go and JavaScript truncate toward zero instead and give -3 and -1, so ported arithmetic is a classic source of off-by-one bugs. Floats follow the same rule: `-7.0 // 2` is -4.0.
code
pycon · 12 lines>>> -7 // 2
-4
>>> -7 % 2
1
>>> 7 // -2
-4
>>> 7 % -2
-1
>>> -7 // -2
3
>>> -7 % -2
-1go deeper
Be able to evaluate -7 // 2 and -7 % 2 on the spot and say the words floor and divisor. Recall that / always gives a float in Python 3 while // floors.
Explain the mechanics: // floors the exact quotient, % is derived from it so the reconstruction identity holds, and the remainder therefore carries the divisor's sign. Work all four sign combinations without hesitating.
Show the production angle - wrap-around indexing and calendar maths are correct by construction in Python but need fix-ups when ported from a truncating language, and a configurable divisor must be guarded against ZeroDivisionError.
Own the interop story: when a specification or a peer service defines remainders with truncating semantics, decide whether to normalise at the boundary or mirror C behaviour internally, and document which convention the codebase speaks.
## The rule, stated once Python's `//` operator performs **floored division**: `a // b` is the largest integer less than or equal to the exact mathematical quotient `a / b`. The exact quotient of -7 and 2 is -3.5. The largest integer that is not greater than -3.5 is **-4**, not -3, so `-7 // 2` evaluates to `-4`. `%` is not chosen independently. Python guarantees the identity ``` a == (a // b) * b + a % b ``` for any integers with a non-zero divisor, so once the quotient is fixed the remainder is forced: ``` -7 % 2 == -7 - ((-7 // 2) * 2) == -7 - (-4 * 2) == -7 + 8 == 1 ``` ## The four sign combinations Work the table by hand once and it stops being memorisation: | expression | exact quotient | floor | `//` | `%` | |---|---|---|---|---| | `7 // 2`, `7 % 2` | 3.5 | 3 | 3 | 1 | | `-7 // 2`, `-7 % 2` | -3.5 | -4 | -4 | 1 | | `7 // -2`, `7 % -2` | -3.5 | -4 | -4 | -1 | | `-7 // -2`, `-7 % -2` | 3.5 | 3 | 3 | -1 | Two observations fall out. First, the magnitude of the remainder is always strictly less than the magnitude of the divisor. Second, and this is the sentence to say in an interview, **the remainder has the sign of the divisor** (or is zero). It never follows the dividend. ## Why Python chose flooring Most C-descended languages truncate toward zero, so in C, C++, Java, Go, Rust and JavaScript `-7 / 2` is -3 and `-7 % 2` is -1. Python deliberately went the other way because flooring makes `%` behave like true modular arithmetic: for a positive `n`, `i % n` lands in `range(n)` for **every** integer `i`, negative ones included. That is exactly what wrap-around code wants. A ring-buffer step backwards is `(i - 1) % capacity` with no correction branch; a weekday shift is `(weekday + delta) % 7`; a hue rotation is `(angle + delta) % 360`. Under truncating semantics each of those needs a fix-up like `((i % n) + n) % n`, and the missing fix-up is one of the most common bugs when arithmetic is ported from C to Python or the other way round. The flooring choice also keeps `//` consistent with `math.floor` on the exact value, which is why `(-7) // 2 == math.floor(-7 / 2)` for values small enough that the float division is exact. ## Floats, and what `//` returns `//` is not "integer division"; it is floor division, and it is defined for floats too. `-7.0 // 2` is `-4.0` and `7.0 // 2` is `3.0`: the *value* is a whole number but the *type* is `float`, because an operation mixing `int` and `float` promotes to `float`. If you need an `int` you must convert explicitly. Float `%` follows the same sign rule, so `-7.0 % 2` is `1.0`. For floats the reconstruction identity holds only up to rounding error, which is why `math.fmod` exists as the C-compatible alternative for float work. ## The zero divisor There is no infinity or NaN escape hatch here. `7 // 0`, `7 % 0`, `7 / 0` and even `7.0 % 0.0` all raise `ZeroDivisionError`, and so does `divmod(7, 0)`. If a divisor can be user-supplied - a page size read from configuration, a bucket count computed from data - guard it rather than relying on a float-style infinity. ## Getting C behaviour when you actually want it Occasionally you genuinely want truncation, usually when reproducing a formula from another language or a specification. The safe forms are `math.trunc(a / b)` or `int(a / b)` for values small enough that the intermediate float is exact, and `math.fmod(a, b)` for the matching remainder. Neither is safe for very large integers, because `a / b` converts to `float` and either loses precision past 2**53 or raises `OverflowError`. A purely integer route is to compute with absolute values and reapply the sign yourself. ## Your own types The behaviour is protocol-driven, not hardwired into the operators. `a // b` calls `type(a).__floordiv__` (falling back to `type(b).__rfloordiv__`), `a % b` calls `__mod__`, and `divmod(a, b)` calls `__divmod__`. When you implement a numeric type, implementing all three consistently - so that the reconstruction identity still holds - is what makes it behave like a real number to the rest of the language.
- What does 7 / 2 return in Python 3, and how does that differ from 7 // 2?`7 / 2` is true division and returns the float `3.5`. It returns a float even when the division is exact, so `6 / 2` is `3.0`, not `3`. `7 // 2` floors the quotient and returns `3` as an `int`. Because `/` produces a float, it loses precision on integers beyond 2**53 and raises `OverflowError` on very large ones, whereas `//` stays exact for any integer.
- How would you reproduce C's truncating -7 / 2 == -3 and -7 % 2 == -1 in Python?For values that fit comfortably in a float, `math.trunc(a / b)` or `int(a / b)` gives the truncated quotient and `math.fmod(a, b)` gives the matching remainder, which takes the sign of the dividend. For large integers avoid the float round trip: compute the floor division and then adjust, or work with `abs()` and reapply the sign, since `a / b` will lose precision or overflow.
- Why is (i - 1) % n a safe way to step backwards through a ring buffer in Python?Because `%` is floored, for a positive `n` the result of `i % n` is always in `range(n)`, including when `i` is negative. So at `i == 0` the expression `(0 - 1) % n` is `n - 1` and wraps to the end with no branch and no fix-up. In a truncating language the same expression yields -1 and indexes out of range, which is why ported code needs the extra `((i % n) + n) % n` dance.
Flooring always steps down to the next stair, even when you are below ground level: from -3.5 you step to -4, not up to -3.
saying these in an interview costs you the question
- Says -7 // 2 is -3 because division truncates toward zero
- Claims % always returns a non-negative result
- Thinks the remainder takes the sign of the dividend
- Calls // integer division and expects an int from 7.0 // 2
- Expects float division by zero to give inf rather than raising