299
votes

According to Google Calculator (-13) % 64 is 51.

According to Javascript (see this JSBin) it is -13.

How do I fix this?

11
essentially a duplicate of How does java do modulus calculations with negative numbers? even though this is a javascript question. - President James K. Polk
Javascript sometimes feels like a very cruel joke - dukeofgaming
google can't be wrong - caub
The fundamental problem is in JS % is not the modulo operator. It's the remainder operator. There is no modulo operator in JavaScript. So the accepted answer is the way to go. - Redu
Why do nearly no languages implement modulo, given how useful it is? - Arnaud

11 Answers

301
votes
Number.prototype.mod = function(n) {
    return ((this%n)+n)%n;
};

Taken from this article: The JavaScript Modulo Bug

186
votes

Using Number.prototype is SLOW, because each time you use the prototype method your number is wrapped in an Object. Instead of this:

Number.prototype.mod = function(n) {
  return ((this % n) + n) % n;
}

Use:

function mod(n, m) {
  return ((n % m) + m) % m;
}

See: http://jsperf.com/negative-modulo/2

~97% faster than using prototype. If performance is of importance to you of course..

33
votes

The % operator in JavaScript is the remainder operator, not the modulo operator (the main difference being in how negative numbers are treated):

-1 % 8 // -1, not 7

18
votes

A "mod" function to return a positive result.

var mod = function (n, m) {
    var remain = n % m;
    return Math.floor(remain >= 0 ? remain : remain + m);
};
mod(5,22)   // 5
mod(25,22)  // 3
mod(-1,22)  // 21
mod(-2,22)  // 20
mod(0,22)   // 0
mod(-1,22)  // 21
mod(-21,22) // 1

And of course

mod(-13,64) // 51
11
votes

The accepted answer makes me a little nervous because it re-uses the % operator. What if Javascript changes the behavior in the future?

Here is a workaround that does not re-use %:

function mod(a, n) {
    return a - (n * Math.floor(a/n));
}

mod(1,64); // 1
mod(63,64); // 63
mod(64,64); // 0
mod(65,64); // 1
mod(0,64); // 0
mod(-1,64); // 63
mod(-13,64); // 51
mod(-63,64); // 1
mod(-64,64); // 0
mod(-65,64); // 63
6
votes

If x is an integer and n is a power of 2, you can use x & (n - 1) instead of x % n.

> -13 & (64 - 1)
51 
4
votes

Though it isn't behaving as you expected, it doesn't mean that JavaScript is not 'behaving'. It is a choice JavaScript made for its modulo calculation. Because, by definition either answer makes sense.

See this from Wikipedia. You can see on the right how different languages chose the result's sign.

2
votes

So it seems that if you're trying to mod around degrees (so that if you have -50 degrees - 200 degrees), you'd want to use something like:

function modrad(m) {
    return ((((180+m) % 360) + 360) % 360)-180;
}
1
votes

I deal with négative a and negative n too

 //best perf, hard to read
   function modul3(a,n){
        r = a/n | 0 ;
        if(a < 0){ 
            r += n < 0 ? 1 : -1
        }
        return a - n * r 
    }
    // shorter code
    function modul(a,n){
        return  a%n + (a < 0 && Math.abs(n)); 
    }

    //beetween perf and small code
    function modul(a,n){
        return a - n * Math[n > 0 ? 'floor' : 'ceil'](a/n); 
    }
1
votes

This is not a bug, there's 3 functions to calculate modulo, you can use the one which fit your needs (I would recommend to use Euclidean function)

Truncating the decimal part function

console.log(  41 %  7 ); //  6
console.log( -41 %  7 ); // -6
console.log( -41 % -7 ); // -6
console.log(  41 % -7 ); //  6

Integer part function

Number.prototype.mod = function(n) {
    return ((this%n)+n)%n;
};

console.log( parseInt( 41).mod( 7) ); //  6
console.log( parseInt(-41).mod( 7) ); //  1
console.log( parseInt(-41).mod(-7) ); // -6
console.log( parseInt( 41).mod(-7) ); // -1

Euclidean function

Number.prototype.mod = function(n) {
    var m = ((this%n)+n)%n;
    return m < 0 ? m + Math.abs(n) : m;
};

console.log( parseInt( 41).mod( 7) ); // 6
console.log( parseInt(-41).mod( 7) ); // 1
console.log( parseInt(-41).mod(-7) ); // 1
console.log( parseInt( 41).mod(-7) ); // 6
0
votes

There is a NPM package that will do the work for you. You can install it with the following command.

npm install just-modulo --save

Usage copied from the README

import modulo from 'just-modulo';

modulo(7, 5); // 2
modulo(17, 23); // 17
modulo(16.2, 3.8); // 17
modulo(5.8, 3.4); //2.4
modulo(4, 0); // 4
modulo(-7, 5); // 3
modulo(-2, 15); // 13
modulo(-5.8, 3.4); // 1
modulo(12, -1); // NaN
modulo(-3, -8); // NaN
modulo(12, 'apple'); // NaN
modulo('bee', 9); // NaN
modulo(null, undefined); // NaN

GitHub repository can be found via the following link:

https://github.com/angus-c/just/tree/master/packages/number-modulo