A. Programming Concepts and Skills · Data Types, Files and ExpressionsInteger Division and Remainders
A1.1 A4.3About 70 minutes
Learning goals- I can use
//, % and divmod() to find quotients and remainders in programs. - I can predict results with negative numbers and explain how Python differs from Java and C.
- I can use remainders to convert units, wrap around, test divisibility and map list positions to rows and columns.
- I can use ceiling division to round a quotient up.
Words to know
integer (floor) division
Division that keeps only the whole-number part of the quotient. In Python a // b rounds the true quotient down (toward negative infinity).
remainder (modulo)
What is left over after integer division. In Python a % b; the result has the same sign as b.
quotient
The result of a division; with //, the number of whole times b fits into a.
division identity
For integers a and b ≠ 0: a == (a // b) * b + a % b. Every language keeps this true.
truncation
Cutting off the decimal part, which rounds toward zero. Java, C and C++ integer division truncate.
ceiling division
Integer division that rounds up, e.g. -(-a // b) or (a + b - 1) // b for positive values.
modular arithmetic
Arithmetic that wraps around after reaching a modulus, like a clock (mod 12) or the days of the week (mod 7).
Why a computer scientist cares about leftovers
Your school is shipping 17 hockey pucks to a tournament in bags of 5. How many full bags? How many pucks are left over? You know this from elementary school: 3 bags, 2 left over.
That tiny calculation is everywhere in computing. A clock app turns 3725 seconds into 1:02:05. A game decides whose turn it is. A photo app turns pixel number 1 000 000 into a row and a column. A banking program checks whether a card number is valid. All of these use integer division and remainders.
In ICS3U you met // and %, mostly with positive numbers, and saw briefly that // rounds down. In this lesson you will use them with confidence: negative numbers, floats, divmod, wrap-around, ceiling division, and the differences between Python and languages such as Java that you may meet in university.
Seventeen hockey pucks packed in bags of 5: 3 full bags (the quotient, 17 // 5) and 2 pucks left over (the remainder, 17 % 5). Check: 3 × 5 + 2 = 17.The two operators
a // b is the quotient: how many whole times b fits into a.a % b is the remainder: what is left over.divmod(a, b) returns both at once as a pair (a // b, a % b).
They are linked by the division identity, which is always true when b is not zero:
a == (a // b) * b + a % b
Dividing by zero with any of the three raises ZeroDivisionError, so guard against a zero divisor whenever it could come from user input or a file.
pucks = 17
per_bag = 5
bags = pucks // per_bag # quotient
extra = pucks % per_bag # remainder
print(bags, extra)
print(divmod(pucks, per_bag)) # both at once, as a tuple
print(bags * per_bag + extra == pucks)
// gives the quotient, % gives the remainder, and divmod gives both. The last line checks the division identity. Output, line by line: 3 2 | (3, 2) | True
Negative numbers: floor, not truncate
The true quotient of −17 ÷ 5 is −3.4. Python's // rounds this down to −4 (the floor). Java, C and C++ instead truncate toward zero and get −3.
Once the quotient is chosen, the remainder is forced by the identity: −17 − (−4)(5) = 3. In Python, a % b always has the same sign as b (or is 0). With a positive divisor, the remainder is always in the range 0 to b − 1.
Python rounds -17 / 5 = -3.4 down to the floor, −4, because −4 × 5 = −20 is the multiple of 5 just below −17. The remainder is the distance up from −20 to −17: 3. So -17 // 5 is -4 and -17 % 5 is 3.print(-17 // 5, -17 % 5)
print(17 // -5, 17 % -5)
print(int(-17 / 5)) # truncates toward zero, like Java
print(7.5 // 2, 7.5 % 2)
With negative numbers Python floors (rounds toward negative infinity), and the remainder takes the sign of the divisor. int(-17 / 5) truncates toward zero instead. With floats, // and % still work but give floats. Output, line by line: -4 3 | -4 -3 | -3 | 3.0 1.5
Memory trick
In Python, % with a positive divisor never gives a negative answer. That is why (day - 3) % 7 safely moves back three days even from Monday (index 0): (0 - 3) % 7 is 4, which is Friday.
Patterns you will use again and again
- Divisibility:
n % k == 0 means k divides n. Even numbers: n % 2 == 0. - Every k-th item:
if i % k == 0: inside a loop (for example, print a progress message every 1000 records). - Unit conversion: seconds to minutes and seconds, cents to dollars and cents, millimetres to metres and millimetres. Use
divmod repeatedly. - Last digit and the rest:
n % 10 is the last digit; n // 10 removes it (Lesson 2 builds whole algorithms on this). - Wrap-around (circular) indexing:
(i + 1) % n moves to the next position and goes back to 0 after the end. - Row and column: for position
i in a grid with cols columns, row = i // cols, col = i % cols, and back again i = row * cols + col. - Ceiling division:
-(-a // b) rounds up without using floats. For positive values (a + b - 1) // b also works.
def hms(total_seconds):
"""Return a clock string h:mm:ss for a whole number of seconds."""
hours, rest = divmod(total_seconds, 3600)
minutes, seconds = divmod(rest, 60)
return f"{hours}:{minutes:02d}:{seconds:02d}"
print(hms(3725))
print(hms(59))
print(hms(86399))
Converting a race time from seconds to hours, minutes and seconds. :02d pads with a zero, so 2 minutes shows as 02. Output, line by line: 1:02:05 | 0:00:59 | 23:59:59
Turning a position in a list into a row and a column. With 4 seats per row, row = i // 4 and column = i % 4. Seat 9 (highlighted) is in row 2, column 1.DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
today = 4 # index of "Fri"
for ahead in [1, 3, 10]:
print(ahead, DAYS[(today + ahead) % 7])
cars, seats = 23, 5
print(-(-cars // seats)) # ceiling division: vans needed
% 7 wraps around the week, so 10 days after Friday is Monday. Ceiling division -(-a // b) rounds a quotient up: 23 people need 5 vans of 5 seats. Output, line by line: 1 Sat | 3 Mon | 10 Mon | 5
Worked exampleExample 1: Making change with Canadian coins
Canada stopped handing out pennies in 2013, so cash totals are rounded to the nearest 5 cents. Write code that takes an amount in cents (already a multiple of 5) and prints how many toonies (200¢), loonies (100¢), quarters (25¢), dimes (10¢) and nickels (5¢) to give, using the fewest coins. Trace it for 385 cents.
- Work in whole cents (an
int), never dollars as a float. That avoids rounding problems (Lesson 6 explains why). - For each coin from largest to smallest: the number of that coin is
amount // value, and what is left is amount % value. divmod gives both. - 385: toonies
385 // 200 = 1, left 185. Loonies 185 // 100 = 1, left 85. Quarters 85 // 25 = 3, left 10. Dimes 10 // 10 = 1, left 0. Nickels 0. - This greedy method gives the fewest coins for Canadian coin values. (It does not work for every coin system, which is a nice question for the sibling unit Algorithm Design and Analysis.)
1 toonie, 1 loonie, 3 quarters, 1 dime, 0 nickels (6 coins). The program is shown below.
COINS = [("toonie", 200), ("loonie", 100), ("quarter", 25), ("dime", 10), ("nickel", 5)]
amount = 385
for name, value in COINS:
count, amount = divmod(amount, value)
print(name, count)
The change-making program from Example 1. count, amount = divmod(amount, value) updates the amount left in one line. Output, line by line: toonie 1 | loonie 1 | quarter 3 | dime 1 | nickel 0
Worked exampleExample 2: Python versus Java with negative numbers
A Java program and a Python program both compute the remainder of −7 divided by 3. Java prints −1 and Python prints 2. Which is right?
- Both are correct for their own definition. Every language must satisfy a = (a div b) × b + (a mod b).
- Java truncates the quotient toward zero: −7 / 3 = −2.33… becomes −2. Then the remainder is −7 − (−2)(3) = −1.
- Python floors the quotient: −2.33… becomes −3. Then the remainder is −7 − (−3)(3) = 2.
- Python's choice means
x % n is always between 0 and n − 1 when n is positive. That is exactly what you want for wrap-around, such as days of the week or array positions. - If you port code between languages, test negative inputs. To get Java's result in Python, use
math.fmod(-7, 3) (a float, −1.0) or int(-7 / 3) for the quotient (careful: / uses floats, so very large integers can lose precision).
Python: -7 // 3 == -3 and -7 % 3 == 2. Java: -7 / 3 == -2 and -7 % 3 == -1. Both obey the division identity.
Just for funWhy did the programmer refuse to share 7 cookies among 2 friends?
Because 7 // 2 is 3 each, and the remainder was obviously 7 % 2, one cookie for the programmer.
Hands-on activityCalendar and clock detective
You need: a paper calendar or the calendar app on a phone, a watch or clock, and Python.
- Pick today's date. Number the days of the week Monday = 0 to Sunday = 6. Use
(today + n) % 7 to predict the weekday of a date 10, 30 and 100 days from today. Check each prediction on the calendar. - Use
divmod to convert your age in days (about years × 365) into weeks and days. - Time how long it takes to tie your shoes or brush your teeth in seconds, then use the
hms function from this lesson to show your longest daily routine as h:mm:ss. - Write one line of code that tells whether the current year is divisible by 4.
What to look for: predictions that match the calendar, correct use of % 7 (not % 6), and an explanation of why 100 days later is 2 weekdays later (100 % 7 = 2).
Your turn
1Give the value of each: 29 // 4, 29 % 4, divmod(29, 4).
7, 1, (7, 1). Check: 7 × 4 + 1 = 29.
2Give the value of -29 // 4 and -29 % 4.
-8 and 3. The true quotient −7.25 is floored to −8, and −29 − (−8)(4) = 3.
3What does print(10 % 2 == 0, 15 % 4 == 0) show?
True False. 10 is divisible by 2; 15 leaves remainder 3 when divided by 4.
4Convert 500 minutes to hours and minutes using divmod.
divmod(500, 60) is (8, 20): 8 hours 20 minutes.
5A list holds 30 photos shown 6 per row. In which row and column (both starting at 0) is photo index 20?
Row 20 // 6 = 3, column 20 % 6 = 2.
6A school needs to rent buses that hold 48 students each. Write an expression for the number of buses needed for n students, without using floats.
-(-n // 48) or (n + 47) // 48. For example 100 students need 3 buses.
7Today is Saturday (index 5, with Monday = 0). Which weekday is 9 days from now?
(5 + 9) % 7 = 14 % 7 = 0, so Monday.
More practice: warm-up
2. It drops the last digit.
3What is 8 // 3 and 8 % 3?
4Which operator gives the remainder in Python?
The program stops with ZeroDivisionError.
More practice: on your own
1Predict the output.
total = 1000print(total // 7, total % 7)print(divmod(-1000, 7))
142 6 and then (-143, 1). 7 × 142 = 994, remainder 6. For −1000: −1000 / 7 ≈ −142.9 floors to −143, and −1000 − (−1001) = 1.
2Predict: print(7.5 // 2, 7.5 % 2).
3.0 1.5. Both work on floats: 2 fits into 7.5 three whole times (3.0), with 1.5 left over.
3A Java student says -11 % 4 is -3. What does Python give, and why do they differ?
Python gives 1. Python floors −2.75 to −3, so the remainder is −11 − (−12) = 1. Java truncates to −2, so its remainder is −11 − (−8) = −3.
4Write a loop that prints the numbers from 1 to 20 that are multiples of 3 or multiples of 5.
for n in range(1, 21): then (indented) if n % 3 == 0 or n % 5 == 0: print(n). It prints 3, 5, 6, 9, 10, 12, 15, 18, 20.
5A pixel is at row 4, column 7 of an image 640 pixels wide. Its pixels are stored in one list, row after row. What is its index, and how do you get row and column back?
Index = 4 × 640 + 7 = 2567. Back: divmod(2567, 640) is (4, 7).
Challenge
1Prove that for a positive divisor b, Python's a % b is always between 0 and b − 1. Use the definition a // b = floor(a / b).
Let q = floor(a/b), so q ≤ a/b < q + 1. Multiply by b > 0: qb ≤ a < qb + b. Subtract qb: 0 ≤ a − qb < b. And a − qb is exactly a % b by the division identity, so 0 ≤ a % b ≤ b − 1 for integers.
2Explain why -(-a // b) equals the ceiling of a / b. Test it on a = 23, b = 5 and a = −23, b = 5.
−(−a // b) = −floor(−a/b), and −floor(−x) = ceiling(x) for any real x. a = 23: −(−23 // 5) = −(−5) = 5 = ceil(4.6). a = −23: −(23 // 5) = −4 = ceil(−4.6). It works for negative a too. ((a + b − 1) // b also gives the ceiling for any integer a when b is positive, but it fails for negative b: a = 20, b = −5 gives −3 instead of −4.)
3Write a function to_java_mod(a, b) that returns the remainder Java would give, using only integer operations (no floats). Test with (−7, 3), (7, −3) and (7, 3).
Java's remainder has the sign of a. One version: r = abs(a) % abs(b) then return r if a >= 0 else -r. Results: (−7, 3) → −1, (7, −3) → 1, (7, 3) → 1. (Floats are avoided because int(a / b) can be wrong for very large integers.)
Check your understandingQuiz
2. What is -9 // 2 in Python?
3. What does divmod(100, 7) return?
4. Which expression is True exactly when n is odd (for any integer n, including negatives)?
5. A list stores a 9-column grid row by row. Which index is row 3, column 5 (starting from 0)?
6. How many 12-egg cartons are needed for 100 eggs?
7. What is -7 % 3 in Python?
For parents and teachersBig idea: expectation A1.1 asks students to use integer division and remainders in programs. The operators are short, but the reasoning (especially with negative numbers) is where marks are lost.
How to help: ask everyday questions and let your teen answer with divmod: How many full weeks and extra days until a birthday? How many 24-packs for a party of 50? What weekday will New Year's Day be? Have them check answers on a calendar.
Common difficulties:
- Expecting
-7 // 2 to be −3. Python floors to −4. - Using
/ and int() for large numbers, which can lose precision because / makes a float. - Forgetting
% 7 when counting days forward, or using % 6. - Off-by-one errors in rows and columns: both start at 0.
- Not guarding against a zero divisor that comes from input.