What the modulo operator does
When you divide one whole number by another, the result has two parts. The quotient is how many times the divisor fits completely. The remainder is what is left over. For 20 divided by 3, the divisor fits 6 times (6 × 3 = 18), and 2 is left over.
In Rust, the / operator on two integers gives the quotient and the % operator gives the remainder. The % operator is called the modulo or remainder operator.
println!("{}", 10 % 2); // 0
println!("{}", 15 % 4); // 3
println!("{}", 20 % 3); // 2
It works with variables as well as literal numbers:
let a: i32 = 2;
let b: i32 = 4;
println!("{}", b % a); // 0
println!("{}", 11 % b); // 3
Quotient and remainder together
Integer division in Rust drops the fractional part, so 15 / 4 is 3, not 3.75. The remainder is the part that was dropped, expressed as a whole number. The two operators always fit together: quotient * divisor + remainder gives back the original number.
let quotient: i32 = 26 / 3;
let remainder: i32 = 26 % 3;
println!("{}", quotient); // 8
println!("{}", remainder); // 2
Check: 8 × 3 + 2 = 26.
Where % is useful
- Leftovers. If you have 70 items and each pack holds 15, then
70 / 15is 4 full packs and70 % 15is the 10 items that do not fill a pack. - Even or odd. A number
nis even whenn % 2is0and odd when it is1. - Divisibility.
n % k == 0meanskdividesnexactly. - Wrapping around. Adding to a position and taking the remainder by the length of a cycle keeps the result in range. If today is day 5 of a 7-day week, then
(5 + 4) % 7is2.
Rust details to know
Negative numbers
For integers, the sign of the result follows the left operand (the dividend):
println!("{}", -7 % 3); // -1
println!("{}", 7 % -3); // 1
If you want a result that is never negative, use the method rem_euclid. With an i32 value, (-7i32).rem_euclid(3) is 2.
Floating-point numbers
The % operator also works on f64 and f32. For example, 7.5 % 2.0 is 1.5. Both operands must have the same type: Rust does not mix an integer and a float in one expression.
Dividing by zero
If the right-hand side of an integer % is zero, the program panics with the message "attempt to calculate the remainder with a divisor of zero". When the divisor is a plain literal 0, the compiler usually catches the mistake before the program runs. When it comes from a variable or user input, check it first.
Augmented form
Like the other arithmetic operators, % has a combined form: x %= 3 means x = x % 3, and it needs a variable declared with let mut.
The exercise
The starter code gives Andy some money and a price per product:
let amount: i32 = 70;
let price: i32 = 15;
Andy buys as many products as he can afford, and the exercise asks for the money left over. Money that does not divide evenly by the price is exactly the remainder, so the whole solution is one line that prints amount % price:
let amount: i32 = 70;
let price: i32 = 15;
println!("{}", amount % price);
Here 15 fits into 70 four times (4 × 15 = 60), so 10 is left, and the program prints 10. Two details matter: println! needs the format string "{}" as its first argument, and the expression to print follows after a comma. Writing println!(amount % price) does not compile.
Common mistakes
- Using
/when you want the leftovers.70 / 15is4, the number of products.70 % 15is10, the money left. - Swapping the operands.
price % amountis15 % 70, which is15, because 70 does not fit into 15 even once. Whenever the left number is smaller than the right one, the remainder is the left number itself. - Treating % as a percentage. It has nothing to do with percentages.
- Expecting a non-negative result for negative inputs. Use
rem_euclidwhen you need that.
Key takeaways
a % bis the remainder of dividingabyb;a / bon integers is the quotient.quotient * divisor + remainderequals the original number.- For integers, the result takes the sign of the left operand;
rem_euclidnever returns a negative number for a positive divisor. - An integer remainder by zero panics.
