Why Does Mod of Operands With Different Signs Produce Wrong Result in JavaScript?

The reason you might be getting the "wrong result" from doing "-x % y" and/or "x % -y" in JavaScript is because "%" operator is actually the remainder operator (which uses truncated division as opposed to floored division which is used for "mod" in the traditional sense).

Modulus, in modular arithmetic, is actually the left over (or remaining) value after the arithmetic division. In programming, the ambiguity between "remainder" and "modulo" arises from the fact that the modulo operation (in general) is not well-defined for negative numbers. Therefore, different programming languages handle it differently. There are three popular implementations:

  1. Truncated Division (used by JavaScript);
  2. Floored Division;
  3. Euclidean Division.

Truncated Division

Truncated division is used for calculating the signed remainder (or what is known as "rem" in some programming languages), where the sign of the result always has the same sign as the dividend. The mathematical formula for it is:

Remainder = Dividend - (Divisor * Quotient)

Where the quotient is calculated as:

Quotient = trunc(Dividend / Divisor)

This means when calculating the quotient, the fractional digits are removed/truncated:

// ES6+
// truncated division
function rem(dividend, divisor) {
    const quotient = Math.trunc(dividend / divisor);
    return (dividend - (divisor * quotient));
}

console.log(rem(5, 3)); // 2
console.log(rem(-5, -3)); // -2
console.log(rem(-5, 3)); // -2
console.log(rem(5, -3)); // 2

As you can see from the example above, when using truncated division, the resulting number always has the same sign as the dividend.

Truncated division is what the "remainder operator" (%) in JavaScript uses:

console.log(5 % 3); // 2
console.log(-5 % -3); // -2
console.log(-5 % 3); // -2
console.log(5 % -3); // 2

Truncated division is also what "%" operator refers to in most other popular programming languages (such as C/C++, C#, Go, Java, Kotlin, Rust, etc.).

Floored Division

Floored division is used for calculating the signed remainder (or what is referred to as "mod" in the traditional sense), where the sign of the result always has the same sign as the divisor. The mathematical formula for it is the same as the one for truncated division — i.e.:

Remainder = Dividend - (Divisor * Quotient)

However, it differs to truncated division in terms of how the quotient is calculated:

Quotient = floor(dividend / divisor)

When calculating the quotient, fractions are rounded down (as opposed to being truncated):

// floored division
function mod(dividend, divisor) {
    const quotient = Math.floor(dividend / divisor);
    return (dividend - (divisor * quotient));
}

console.log(mod(5, 3)); // 2
console.log(mod(-5, -3)); // -2
console.log(mod(-5, 3)); // 1
console.log(mod(5, -3)); // -1

As you can see from the example above, when using floored division, the resulting number always has the same sign as the divisor.

The floored-mod function can also be written using the JavaScript remainder operator (%), like so:

// floored division
function mod(dividend, divisor) {
    return ((dividend % divisor) + divisor) % divisor;
}

console.log(mod(5, 3)); // 2
console.log(mod(-5, -3)); // -2
console.log(mod(-5, 3)); // 1
console.log(mod(5, -3)); // -1

Floored division is what "%" operator refers to in some programming languages (such as Python, Ruby, Perl, etc.). It also exists in some form in other programming languages (such as Java, Kotlin, etc.).

Euclidean Division

Euclidean division is used for ensuring the remainder is always non-negative. This is to ensure consistency with the Euclidean division algorithm. The mathematical formula for it is:

Remainder = Dividend - (abs(Divisor) * Quotient)

Where the quotient is calculated as:

Quotient = floor(Dividend / abs(Divisor))

This means when calculating the quotient, fractions are rounded down and the divisor is always positive:

// euclidean division
function remEuclid(dividend, divisor) {
    const absDivisor = Math.abs(divisor);
    const quotient = Math.floor(dividend / absDivisor);
    return (dividend - (absDivisor * quotient));
}

console.log(remEuclid(5, 3)); // 2
console.log(remEuclid(-5, -3)); // 1
console.log(remEuclid(-5, 3)); // 1
console.log(remEuclid(5, -3)); // 2

The euclidean-remainder function can also be written using the JavaScript remainder operator (%) in the following way:

// euclidean division
function remEuclid(dividend, divisor) {
    const mod = ((dividend % divisor) + divisor) % divisor;
    return mod < 0 ? mod + Math.abs(divisor) : mod;
}

console.log(remEuclid(5, 3)); // 2
console.log(remEuclid(-5, -3)); // 1
console.log(remEuclid(-5, 3)); // 1
console.log(remEuclid(5, -3)); // 2

Rust and Go are two popular programming languages that include a built-in function for calculating the euclidean remainder.


This post was published by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.