What the modulo operator does
The modulo operator % gives the remainder left over when one number is divided by another. In a division, the quotient counts how many times the divisor fits completely, and the remainder is what is left after that.
For 15 divided by 4, the divisor fits 3 times (3 × 4 = 12) and 3 is left over:
console.log(10 % 2); // 0
console.log(15 % 4); // 3
console.log(20 % 3); // 2
It works the same way with variables:
let a = 2;
let b = 4;
console.log(b % a); // 0
console.log(11 % b); // 3
Getting the quotient too
TypeScript has no separate integer division operator. The / operator always works on number values, which are floating-point, so 7 / 2 is 3.5, not 3. To get the whole-number quotient, round the result of the division down with Math.floor, which returns the largest integer that is less than or equal to its argument:
let quotient = Math.floor(26 / 3);
let remainder = 26 % 3;
console.log(quotient); // 8
console.log(remainder); // 2
The two results fit back together: quotient * divisor + remainder gives the original number. Here 8 × 3 + 2 is 26.
Reading a division as a quotient and a remainder
A useful habit is to split any division into its two parts before writing code. For 17 divided by 5, ask how many whole fives fit into 17 (3, which is 15) and how much is left (2). In code, Math.floor(17 / 5) gives the 3 and 17 % 5 gives the 2. If the remainder is 0, the division was exact. If it is not 0, it is always smaller than the divisor, which is why a remainder by 5 can only be 0, 1, 2, 3 or 4.
That last fact is what makes % so handy: no matter how large the left number gets, the result stays inside a small, known range.
The lesson's exercise
Andy has amount dollars, and each product costs price dollars. The task is to print how much money is left after buying as many products as possible. Whatever does not divide evenly by the price is exactly that leftover, so the answer is the remainder of amount divided by price.
The starter code declares the two variables:
let amount: number = 70;
let price: number = 15;
The instructions ask for the remainder directly, so no division is needed, and the quotient (how many products Andy can buy) is not printed. Add one line that prints amount % price with console.log. The price fits 4 times into 70 (4 × 15 = 60), so 10 is left over and the program prints 10:
let amount: number = 70;
let price: number = 15;
console.log(amount % price);
The annotation : number only tells the compiler what kind of value each variable holds. It is removed when the code is compiled to JavaScript and has no effect on the result.
Gotchas
- The sign follows the left operand. In TypeScript, as in JavaScript, the result of
%takes the sign of the number on the left.-7 % 3is-1and7 % -3is1. It is a remainder, not a "always between 0 and the divisor" modulo as in some other languages. To force a non-negative result for a positive divisorm, use((x % m) + m) % m; forx = -7andm = 3that gives2. - It works on decimals.
5.5 % 2is1.5. Floating-point rounding can make such results look odd:0.3 % 0.1prints0.09999999999999998. - Dividing by zero does not crash.
5 % 0givesNaN, a special "not a number" value, and no error is raised. Math.floorand negatives.Math.floor(-7 / 2)is-4, because it rounds toward negative infinity. If you want to drop the decimal part instead, useMath.trunc(-7 / 2), which gives-3. Withtrunc, the quotient and%match:-3 * 2 + (-7 % 2)is-7.
Where % is useful
- Even or odd.
n % 2 === 0is true for even numbers. - Wrapping around. With days numbered 0 to 6, the day three days after day 5 is
(5 + 3) % 7, which is1. - Divisibility.
a % b === 0meansbdividesaevenly.
Key takeaways
a % bis the remainder of dividingabyb.- The whole-number quotient comes from
Math.floor(a / b), because/never rounds on its own. - The result of
%has the sign of the left operand. - Remainder by zero gives
NaN.