What the modulo operator does
When you divide one whole number by another, the quotient is how many times the divisor fits completely, and the remainder is what is left over. In Go, the % operator, called modulo, gives the remainder:
fmt.Println(10 % 2) // 0
fmt.Println(15 % 4) // 3
fmt.Println(20 % 3) // 2
Reading the second line: 4 fits into 15 three times (3 * 4 = 12), and 15 - 12 leaves 3. With variables it works the same way:
a := 2
b := 4
fmt.Println(b % a) // 0
fmt.Println(11 % b) // 3
% is defined for integers. A float64 operand is a compile error; for decimal remainders the standard math package has math.Mod.
Quotient and remainder together
Integer division with / gives the quotient. When both operands are integers, Go drops the fractional part. The two operators are a pair:
quotient := 26 / 3
remainder := 26 % 3
fmt.Println(quotient) // 8
fmt.Println(remainder) // 2
They always satisfy quotient * divisor + remainder == dividend. Here, 8 * 3 + 2 is 26.
Where the remainder is useful
- Left-over amounts. What remains after buying as many items as you can afford.
- Divisibility.
n % 2 == 0is true whennis even, andn % k == 0tells you whetherkdividesnexactly. The remainder is 0 only for exact multiples. - Cycling through a fixed range. A remainder is always smaller than the divisor, so
i % 3walks through 0, 1, 2, 0, 1, 2 asiincreases. This pattern wraps an index around a list or a clock. - Splitting a value into parts. The remainder after dividing by 60 turns a number of seconds into the seconds part of a minutes-and-seconds display.
Details specific to Go
The sign of the result
Go truncates integer division toward zero, and the remainder takes the sign of the left operand:
fmt.Println(-7 % 2) // -1
fmt.Println(7 % -2) // 1
If you expect a result between 0 and the divisor when the left side can be negative, such as when wrapping an index, add the divisor and take the remainder again: (i % n + n) % n.
Division by zero
Dividing by zero is an error, and so is taking a remainder by zero. A zero constant in the code is caught when the program compiles. A variable that holds zero compiles but makes the program stop at run time with runtime error: integer divide by zero.
Precedence
% ranks with * and /, above + and -, and those operators run from left to right. For example, 10 - 4 % 3 * 2 is 10 - ((4 % 3) * 2), which is 8.
The lesson's exercise
Andy has amount dollars, and each product costs price dollars. The task: print how much money Andy has left after buying as many products as he can. Money left is whatever does not divide evenly by the price, which is the remainder.
amount := 70
price := 15
fmt.Println(amount % price)
The output is 10. Andy can buy 4 products (70 / 15 is 4 in integer division), which cost 60 dollars, and 70 - 60 leaves 10.
As a reading aid, 17 % 5 is 2, because 5 fits 3 times into 17 and 2 are left over. Think of the same pattern with the lesson's numbers: 15 fits 4 times into 70, and 10 remains.
Common mistakes and gotchas
- Using
/instead of%.amount / priceis 4, the number of products, not the leftover money. - Remainder of a smaller number. If the left side is smaller than the right, the remainder is the left side:
3 % 5is 3, and5 % 5is 0. - Swapping the operands.
price % amountis 15 % 70, which is 15. The order matters. - Using
%on decimals. The compiler rejects it forfloat64values. - Negative values. The result follows the sign of the left operand, so
-7 % 2is -1, which makes an even-or-odd test liken % 2 == 1miss negative odd numbers. Compare with 0,n % 2 != 0, instead.
Key takeaways
a % bis the remainder of dividingabyb, anda / bwith integers is the quotient.- A remainder of 0 means the division is exact.
- In Go the result takes the sign of the left operand, and both operands must be integers.
- Dividing or taking a remainder by zero is an error.