Integer division in Python uses the // operator, and it floors the result toward negative infinity rather than truncating toward zero. So 7 // 2 is 3, and -7 // 2 is -4, not -3. That negative case surprises everyone coming from C or Java, where integer division truncates. Python’s choice is deliberate and it keeps a useful identity true: a == (a // b) * b + (a % b). Once you know the rule is floor, not truncate, the sign behaviour stops being mysterious.
Table of contents
- The two division operators
- Floor, not truncate: the negative surprise
- How // and % stay consistent
- divmod: both answers at once
- When floats sneak into floor division
- How this fits the rest of the stack
- FAQ
The two division operators
Python has two:
7 / 2 # 3.5 - true division, always a float
7 // 2 # 3 - floor division, drops the fraction
/ always gives a float, even when the result is whole (4 / 2 is 2.0, not 2). // gives the floor of the division. For two positive integers, // behaves exactly as you expect - it is division with the fractional part thrown away.
The float-versus-int distinction matters on its own: if you index a list with length / 2 you get a TypeError, because that is a float. length // 2 gives an int and works. Reaching for // when you need an integer index is the most common everyday use of the operator.
Floor, not truncate: the negative surprise
The interesting behaviour is with negatives:
7 // 2 # 3
-7 // 2 # -4 not -3
7 // -2 # -4
-7 // -2 # 3
-7 / 2 is -3.5. Flooring means going to the nearest integer that is less than or equal, and the integer just below -3.5 is -4. Truncation, which C and Java use, would chop the .5 and give -3. Python floors, so it gives -4.
This is the single fact to remember: // rounds down, toward negative infinity, not toward zero. For positive numbers down and toward zero are the same direction, which is why the difference only shows up with a negative operand. If you specifically want truncation toward zero, use int(a / b) or math.trunc.
How // and % stay consistent
Floor division and the modulo operator % are designed together so this identity always holds:
a == (a // b) * b + (a % b)
Check it with -7 and 2: -7 // 2 is -4, -7 % 2 is 1, and (-4) * 2 + 1 is -7. It balances. This is why Python’s % returns a result with the same sign as the divisor:
-7 % 2 # 1 (sign follows the divisor, 2)
7 % -2 # -1
In C, % can return a negative remainder, which makes is this even checks and clock-arithmetic wrap-arounds fiddly. Python’s floor-based % means n % 12 is always in 0..11 for a positive divisor, no matter the sign of n - which is exactly what you want for indexing into a cycle.
divmod: both answers at once
When you need the quotient and the remainder together - and you often do, for splitting a total into units - divmod gives you both in one call:
divmod(17, 5) # (3, 2) -> 3 fives and 2 left over
# seconds into minutes and seconds
minutes, seconds = divmod(125, 60) # (2, 5)
It is one operation instead of two, it cannot disagree with itself, and it reads clearly. Any time you compute a // b and a % b on the same pair of numbers, divmod is the tidier form. It is the natural tool for converting a flat count into mixed units - seconds to minutes, cents to dollars-and-cents, items to full-boxes-and-remainder.
When floats sneak into floor division
// works on floats too, and there it returns a float:
7.0 // 2 # 3.0 - a float, floored
7.5 // 2 # 3.0
The floor logic is the same, but the result type follows the operands, so a single float anywhere makes the result a float. That matters if you then use the value as an index or feed it to something that insists on an int - you may need an explicit int(...) around it.
The clean rule: keep integer math on integers. If both operands are int, // stays int. Let a float in, and you are back to floating-point representation and a float result. For index math, counters, and pagination, keep everything int and reach for // deliberately rather than / followed by a cast.
How this fits the rest of the stack
Getting division right - floor versus truncate, the sign of the remainder, integer versus float - is the kind of detail that decides whether pagination lands on the right row or a scheduler fires at the right minute. When that logic runs as a job or an API behind real traffic, the arithmetic and the runtime both need to behave the way you expect every time. The RunxBuild hosting calculator lays out the service, database, storage, and bandwidth as separate line items, and the RunxBuild dashboard is where the team watches deploys, logs, and restarts as they happen.
Useful related references:
- Change Python Version: The Three Tools That Make It Stop Hurting
- Deploy a Python API for Free on RunxBuild
- django-admin Not Found: Fix the Command Without Guessing Which Python You Used
- Python services on RunxBuild
FAQ
What is integer division in Python?
It is division that discards the fractional part, done with the // operator. 7 // 2 is 3. Unlike /, which always returns a float, // returns an integer when both operands are integers, which is what you want for indexes and counters.
Why is -7 // 2 equal to -4 in Python?
Because // floors toward negative infinity rather than truncating toward zero. -7 / 2 is -3.5, and the largest integer less than or equal to -3.5 is -4. C and Java truncate and give -3; Python floors and gives -4. The difference only appears with a negative operand.
What is the difference between / and // in Python?
/ is true division and always returns a float, even for whole results - 4 / 2 is 2.0. // is floor division and returns the floored quotient, an integer when both operands are integers. Use // when you need an integer, such as a list index.
Why is Python’s modulo result never negative for a positive divisor?
Because % is defined to keep the identity a == (a // b) * b + (a % b) consistent with floor division, so its result takes the sign of the divisor. For a positive divisor, n % b is always in the range 0 to b-1, which makes cyclic indexing straightforward.
How do I get both the quotient and remainder in Python?
Use divmod(a, b), which returns a tuple (a // b, a % b) in one call. It is the tidy way to split a total into units, such as divmod(125, 60) giving (2, 5) for minutes and seconds.