Why -7 % 3 gives different answers in different languages
-7 % 3 is 2 in Python but -1 in JavaScript, Java, C and Go. Truncated, floored and Euclidean division explained, and how to get a non-negative remainder.
Walk backwards around an array with (i - 1) % n, and when i is 0, Python gives n - 1 while JavaScript gives -1 and reads undefined. Once a negative number is involved, languages define % differently.
Which way the quotient is rounded
Divide an integer a by a non-zero integer b, and the integer quotient q and remainder r must satisfy a = b × q + r. Adding |r| < |b| still does not pin down one answer. For -7 ÷ 3, both (q = -2, r = -1) and (q = -3, r = 2) fit. What decides the remainder is how the real quotient, -2.33…, is turned into an integer.
| Method | Quotient q | Sign of r | -7 ÷ 3 | 7 ÷ -3 |
|---|---|---|---|---|
| Truncated | rounded toward zero | follows the dividend, on the left | q -2, r -1 | q -2, r 1 |
| Floored | rounded toward −∞ | follows the divisor, on the right | q -3, r 2 | q -3, r -2 |
| Euclidean | chosen so 0 ≤ r < |b| | never negative | q -3, r 2 | q -2, r 1 |
All three satisfy a = b × q + r, but only Euclidean division always gives a non-negative remainder. With two positive operands, they all agree.
What each language picked
| Language | -7 % 3 |
Method |
|---|---|---|
| Python | 2 |
floored, paired with // |
| JavaScript, Java, C, C++, Go | -1 |
truncated |
| JavaScript BigInt | -1n (-7n % 3n) |
truncated |
If a language has an operator that returns the integer quotient, such as Python’s //, integer / in Java, C, C++ and Go, or BigInt /, that quotient and % satisfy the identity above. In C and C++, this is conditional on the quotient being representable.
Plain JavaScript numbers are different. -7 / 3 is not an integer quotient but the floating-point value -2.33…, so (a / b) * b + a % b is not this integer identity. The % operation truncates the exact mathematical quotient independently. How floats are stored is covered in our floating-point post.
Where it bites
An odd-number check written as n % 2 == 1 fails in truncating languages because -3 leaves -1. n % 2 != 0 works in all of them.
When you need a value from 0 to n − 1, as with a circular index, add n only when the remainder is negative.
// For circular indexes. n is a positive integer.
function wrapIndex(i, n) {
const r = i % n;
return r < 0 ? r + n : r + 0; // + 0 turns -0 into 0
}
wrapIndex(-1, 5); // 4
When a negative number divides exactly, as in -5 % 5, JavaScript returns -0. That still works as an index, but Object.is(-0, 0) is false, so the helper adds 0 to remove the sign.
Standard-library functions are also available. Math.floorMod(-7, 3) and Rust’s (-7i32).rem_euclid(3) both return 2. They part ways when the divisor is negative. floorMod uses floored division, so Math.floorMod(4, -3) is -2. rem_euclid is Euclidean, so 4i32.rem_euclid(-3) is 1.