PYTHON / OPERATORS
Arithmetic operators and integer division
Use Python's arithmetic operators confidently, and predict what / , // , % and divmod return for positive, negative, and float operands.
What you will learn
- Predict when an expression returns int and when it returns float
- Compute a // b and a % b correctly when either operand is negative
- Use divmod to get quotient and remainder in one step
- Apply the identity (a // b) * b + a % b == a to check your reasoning
Understanding Arithmetic operators and integer division
Python has seven arithmetic operators: +, -, *, / (true division), // (floor division), % (remainder), and ** (power). The type of the result depends on the operator, not only on the operands: / always produces a float, so 8 / 4 is 2.0 and not 4. The other operators keep int results when both operands are ints, and Python ints have no fixed width, so 10 ** 30 is computed exactly instead of overflowing.
Floor division does not chop off the fractional part; it rounds the mathematical quotient down toward negative infinity. That is why 17 // 5 is 3 but -17 // 5 is -4: floor(-3.4) is -4, not -3. Languages like C and Java truncate toward zero instead, which is why programmers coming from them are surprised here.
The % operator is defined so that (a // b) * b + a % b == a always holds. Because the quotient is floored, the remainder ends up with the same sign as the divisor: -17 % 5 is 3, while 17 % -5 is -3. This makes % useful for cyclic indexing, since i % n stays in range(n) even when i is negative, and divmod(a, b) hands you both the floored quotient and that remainder as a tuple.
a, b = 17, 5
print(a + b, a - b, a * b)
print(a / b)
print(a // b, a % b)
print(a ** b)
print(-a // b, -a % b)
print(a // -b, a % -b)
print(divmod(-a, b))
print(8 / 4, 7.0 // 2)Floor division rounds toward negative infinity and the remainder takes the sign of the divisor, while / always yields a float.
Worked examples
Splitting a total with divmod
Breaking a number of seconds into hours, minutes and seconds using repeated floor division and remainder.
total = 3725
hours, rest = divmod(total, 3600)
minutes, seconds = divmod(rest, 60)
print(hours, minutes, seconds)
print(f"{hours}:{minutes:02d}:{seconds:02d}")Example explained
Line 1divmod(3725, 3600) returns (1, 125): one whole hour and 125 seconds left over.
Line 2divmod(125, 60) returns (2, 5), so the leftover splits into 2 minutes and 5 seconds.
Line 3Both results stay ints because divmod on ints never switches to float, so they format cleanly with :02d.
Signs of quotient and remainder
Shows that the remainder follows the divisor's sign and that the quotient/remainder identity always holds.
for a in (7, -7):
for b in (2, -2):
q, r = a // b, a % b
print(a, b, q, r, q * b + r == a)Example explained
Line 17 // -2 is -4 because floor(-3.5) is -4, so the quotient moves away from zero, not toward it.
Line 2The remainder is -1 when b is -2 and 1 when b is 2: its sign copies the divisor, never the dividend.
Line 3The last column is True in every row, confirming q * b + r == a is the rule that fixes both values.
Why / breaks indexing
Demonstrates that true division returns a float even for exact divisions, which list indices reject.
items = ["a", "b", "c", "d", "e"]
try:
print(items[len(items) / 2])
except TypeError as e:
print("TypeError:", e)
print(items[len(items) // 2])Example explained
Line 1len(items) / 2 evaluates to 2.5, a float, and indexing refuses floats even if they are whole numbers.
Line 2len(items) // 2 evaluates to the int 2, which indexes the middle element "c".
Line 3Even with an even length, / would give 2.0 and still fail, so // is the right tool for index math.
Important notes
// on a float operand still returns a float: 7.0 // 2 is 3.0, and the result is a rounded-down float, not an int.
1 / 0 raises ZeroDivisionError: division by zero, while 1 // 0 and 1 % 0 raise ZeroDivisionError: integer division or modulo by zero; the exception type is the same.
Common mistakes
Using / for counts, sizes or indices: the float result silently spreads through the program and later raises TypeError at an index or range() call.
Assuming -7 // 2 is -3 like truncating languages; it is -4, which produces off-by-one loop counts and page totals.
Assuming n % 3 is always non-negative; 7 % -3 is -2, so a positive-only assumption breaks as soon as the divisor is negative.
Try it yourself
Change, predict, then run
Write code that turns a total in cents into dollars and cents with divmod and prints it as "$D.CC". Run it with 1234 and then with -1234, and note how floor division changes the dollar figure.
Open the Python workspaceCheck your understanding
What do q and r hold after q, r = -9 // 4, -9 % 4?
- -3 and 3
- -2 and -1
- -3 and -1
- -2 and 3
Show answer
-9 / 4 is -2.25, and // rounds down to -3, so r must satisfy -3 * 4 + r == -9, giving r = 3. The tempting -2 and -1 comes from truncating toward zero, which is how C behaves but not Python.