370

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

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

How do I fix this?

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Alec Gorge
  • 17,110
  • 10
  • 59
  • 71
  • This may just be a precedence issue. Do you mean `(-13) % 64` or `-(13 % 64)`? Personally, I'd put in the parens either way, just for extra clarity. – Tyler Dec 17 '10 at 03:59
  • 4
    essentially a duplicate of [How does java do modulus calculations with negative numbers?](http://stackoverflow.com/questions/4403542/how-does-java-do-modulus-calculations-with-negative-numbers) even though this is a javascript question. – President James K. Polk Dec 18 '10 at 00:22
  • 24
    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 May 04 '17 at 20:59
  • 3
    Which one did you mean to fix, Google or JS? – Arnaud Apr 15 '19 at 19:22
  • 6
    Why do nearly no languages implement modulo, given how useful it is? – Arnaud Jan 14 '21 at 08:39

13 Answers13

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

Taken from this article: The JavaScript Modulo Bug

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Enrique
  • 9,920
  • 7
  • 47
  • 59
  • 33
    I don't know that I would call it a "bug". The modulo operation is not very well defined over negative numbers, and different computing environments handle it differently. Wikipedia's article on the [modulo operation](http://en.wikipedia.org/wiki/Modulo_operation) covers it pretty well. – Daniel Pryden Dec 17 '10 at 04:08
  • 34
    It may seems dumb since it is often called 'modulo', suggesting it would behave the same as its mathematics definition (see ℤ/nℤ algebra), which it does not. – etienne Apr 25 '13 at 16:41
  • 9
    Why take the modulo before adding n? Why not just add n and then take the modulo? – starwed Nov 26 '13 at 22:34
  • 21
    @starwed if you didn't use this%n it would fail for `x < -n` - e.g. `(-7 + 5) % 5 === -2` but `((-7 % 5) + 5) % 5 == 3`. – fadedbee Feb 06 '14 at 21:58
  • 1
    Interesting theory, but `Number.prototype.mod` has no effect in modern browsers - at least Firefox 28, Chromium 32. – NoBugs Feb 23 '14 at 08:27
  • @NoBugs - It works perfectly for me in Firefox 28 and Chrome 34. (Why wouldn't it?) – nnnnnn Apr 18 '14 at 23:30
  • @nnnnnn It's never defined by default, Firefox or Chromium, for me - the only way to use it would be if you define Number.prototype.mod, and call it as Number.prototype.mod. See: http://i.imgur.com/nU4kUIX.png – NoBugs Apr 19 '14 at 04:48
  • 3
    @NoBugs - Nobody said it was defined by default. The code in this answer is what defines it. Having run that code you can then say `(-13).mod(64)` and get `51`. http://jsfiddle.net/63KyC/ – nnnnnn Apr 19 '14 at 13:25
  • 1
    I see, from this posting I implied that .mod overwrote the % mod behavior - if so, the function would be a native method first. So this method would actually be no different than doing `Number.prototype.myfunction = ...` – NoBugs Apr 19 '14 at 18:09
  • 13
    I recommend to add to the answer that to access this function one should use the format (-13).mod(10) instead of -13 % 10. It would be more clear. – Jp_ Dec 01 '16 at 10:58
  • 2
    JavaScript calculates the remainder which is different from modulo – Panos Kalatzantonakis Sep 02 '17 at 17:46
  • This will overflow for very large n (sorry, too much time working with Ethereum) – William Entriken Apr 10 '18 at 16:54
  • In [*§20.3.1.13MakeDay*](http://ecma-international.org/ecma-262/8.0/#sec-makeday) the *modulo* operation specified behaves as for the mathematic sense, e.g. `-1 modulo 12` is 11, but `-1 % 12` is -1. It even makes this explicit in [*§5.2 Algorithm Conventions*](http://ecma-international.org/ecma-262/8.0/#sec-makeday) where it says: "*The notation “x modulo y” (y must be finite and nonzero) computes a value k of the same sign as y (or zero) such that abs(k) < abs(y) and x-k = q × y for some integer q.*", which is not how the `%` operator works. – RobG Apr 21 '18 at 00:05
  • 2
    Note also that `%` is now called a [*MultiplicativeOperator*](http://ecma-international.org/ecma-262/8.0/#prod-MultiplicativeOperator) and is compared to the C and C++ remainder operator. – RobG Apr 21 '18 at 00:12
  • 1
    The link you provided seems to be dead – Little geek Aug 20 '18 at 11:54
  • 3
    @etienne is incorrect. In math, it's definitely true that, for example -1 % 12 = -1. That's because in mod 12 algebra, -1 = 11. They are distinct symbols referring the same equivalence class. – Adam the Impaler Dec 26 '18 at 07:11
  • 1
    As per https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder, JavaScript returns the "remainder", which by definition "always takes the sign of the dividend". – infojunkie Nov 01 '20 at 19:49
  • This breaks precision when there are too many digits after decimal point because. – Taylan Nov 22 '20 at 21:31
  • 1
    `const mod = (n, m) => ((n % m) + m) % m;` – Roko C. Buljan Apr 08 '21 at 10:59
  • The `%` operator is the REMAINDER OPERATOR not the modulo operator!!! – asdf3.14159 Jul 02 '21 at 08:09
248

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: https://jsperf.app/negative-modulo/2

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

StuR
  • 12,042
  • 9
  • 45
  • 66
  • 1
    Great tip. I took your jsperf and compared with the rest of the solutions in this question (but it seems this is the best anyway): http://jsperf.com/negative-modulo/3 – Mariano Desanze Oct 12 '13 at 14:16
  • 23
    Micro-optimisation. You'd have to be doing a *massive* amount of mod calculations for this to make any difference whatsoever. Code what's clearest and most maintainable, then optimise following performance analysis. – ChrisV Nov 08 '14 at 12:13
  • I think you've got your `n`s and `m`s around the wrong way in your second example @StuR . It should be `return ((n % m) + m) % m;`. – OdinX Mar 16 '15 at 00:44
  • This should be a comment to the accepted answer, not an answer for itself. – xehpuk Feb 06 '18 at 22:23
  • 31
    The motivation stated in this answer is a micro-optimization, yes, but modifying the prototype is problematic. Prefer the approach with the fewest side-effects, which is this one. – Keen May 08 '18 at 01:47
  • This breaks precision when there are too many digits after decimal point because. – Taylan Nov 22 '20 at 21:31
  • I would strongly disagree. There is no practical reason not to it the way in the accepted answer. You say it's slower because the number is wrapped in an object... that happens anyway... 99% of use cases the number you call "n" in your function will already be a number object. This kind of optimisation is not important to anyone. You're splitting milliseconds over thousands of operations, if you need that kind of performance then why the hell are you doing this in Javascript? – JeneralJames Apr 23 '21 at 07:59
  • @Keen what exactly do you think is problematic about modifying the prototype? Countless JS libraries do that all the time and it is even given as a feature of JS and encouraged. One of the great powers of JS is the ability to extend and override native functionality. If we can't do that, you can forget about polyfills and old browser support. – JeneralJames Apr 23 '21 at 08:03
  • 5
    @JeneralJames The main problem with altering the prototype is namespace collisions. At the end of the day it's just a mutation of global data. Mutating globals is bad practice outside of small throwaway code. Export a function as a trackable dependency. Polyfills as an exception to the rule are irrelevant here. This isn't a polyfill. Real polyfills follow standards which make collisions safe. If you want to argue this in principle, there's a separate question for it. https://stackoverflow.com/questions/6223449/why-is-it-frowned-upon-to-modify-javascript-objects-prototypes – Keen May 20 '21 at 00:06
  • "*each time you use the prototype method your number is wrapped in an Object*" - but that's not because of using prototype methods, that's because using sloppy-mode methods. Don't do that, no performance problems. (Extending native prototypes is still not recommended, of course). – Bergi Jun 27 '22 at 10:23
40

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

Rob Sobers
  • 20,737
  • 24
  • 82
  • 111
  • 13
    It *should* be called the remainder operator but it *is* called modulus operator: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Arithmetic_operators – Big McLargeHuge Oct 21 '13 at 22:54
  • 21
    @DaveKennedy: MDN is not an official language reference, it's a community-edited site which sometimes gets it wrong. [The spec](http://www.ecma-international.org/ecma-262/8.0/index.html#sec-applying-the-mod-operator) does not call it a modulo operator, and as far as I can tell it never has (I went back to ES3). It explicitly says the operator yields the remainder of an implied division, and just calls it "the % operator." – T.J. Crowder Jul 22 '17 at 14:07
  • 4
    If it is called `remainder`, it must be larger than 0 by definition. Can't you remember the **division theorem** from high school?! So maybe you can have a look here: https://en.wikipedia.org/wiki/Euclidean_division – Ahmad Jan 17 '20 at 17:17
  • @Ahmad—it's now called a [multiplicative operator](https://tc39.es/ecma262/#sec-multiplicative-operators). – RobG Dec 14 '20 at 00:11
  • 8
    "mod" should have been implemented into every language form the start. After 30 years of programming, I --never-- needed a % b when a is negative: every single time, what I needed instead was mod(a,b). – Arnaud Jan 14 '21 at 08:37
20

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
Shanimal
  • 11,517
  • 7
  • 63
  • 76
  • 1
    Oops, the link you specified actually references `#sec-applying-the-mod-operator` right there in the url :) Anyway, thanks for the note, I took the fluff out of my answer, it's not really important anyway. – Shanimal Jul 25 '17 at 00:31
  • 4
    @ Shanimal: LOL! It does. An error by the HTML editor. The spec text does not. – T.J. Crowder Jul 25 '17 at 06:34
13

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
wisbucky
  • 33,218
  • 10
  • 150
  • 101
  • 14
    If javascript changed the modulo operator to match the mathematical definition, the accepted answer would still work. – starwed Nov 26 '13 at 22:33
  • 30
    _"What if Javascript changes the behavior in the future?"_ - Why would it? Changing the behaviour of such a fundamental operator is not likely. – nnnnnn Apr 18 '14 at 23:33
  • 2
    +1 for sharing this concern-of & alternative-to the featured answer #answer-4467559 &for *4* reasons: (1) Why it states,& yes“Changing the behaviour of such a fundamental op is not likely” but still prudent to consider even to find it's not needed. (2) defining a working op in terms of a broken one, while impressive, is worrysome at least on 1st look, at is should be til shown not (3) tho I hvnt well-verified this alternative, I find easer to follow on quick look. (4)tiny: it uses 1 div+1 mul instead of 2 (mod) divs& I've heard on MUCH earlier hardware w/o a good FPU,multiplication was faster. – Destiny Architect May 07 '15 at 23:33
  • 2
    @DestinyArchitect it's not prudent, it's pointless. If they were to change the behaviour of the remainder operator, it would break a good range of programs using it. That's never going to happen. – Aegis Feb 02 '16 at 23:16
  • 25
    What if the behavior of `-`, `*`, `/`, `;`, `.`, `(`, `)`, `,`, `Math.floor`, `function` or `return` changes? Then your code is horribly broken. – xehpuk Feb 06 '18 at 22:19
  • what if the behavior of the minus operator changes? :-) – Gianluca Ghettini Jun 06 '19 at 14:34
  • 1
    I just did some profiling, and it looks like despite the apparently greater complexity, this approach is between 4 and 8 times faster than the accepted answer (at least in the current version of node). – Logan R. Kearsley Dec 16 '20 at 23:17
  • 1
    This version also never returns `-0`, which makes it superior to the accepted answer in my view. `-0` is evil. – McMath Aug 31 '21 at 06:16
8

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 
Panos Kalatzantonakis
  • 12,525
  • 8
  • 64
  • 85
quasimodo
  • 3,050
  • 1
  • 14
  • 5
7

Fix negative modulo (reminder operator %)

Simplified using ES6 Arrow function, and without dangerously extending the Number prototype

const mod = (n, m) => (n % m + m) % m;

console.log(mod(-90, 360));    //  270  (Instead of -90)
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
5

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.

dheerosaur
  • 14,736
  • 6
  • 30
  • 31
4

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
zessx
  • 68,042
  • 28
  • 135
  • 158
  • 2
    In euclidian function checking m < 0 is useless because ((this%n)+n)%n is always positive – bormat May 05 '16 at 09:07
  • 1
    @bormat Yes it is, but in Javascript `%` can return negative results (an this is the purpose of these functions, to fix it) – zessx May 06 '16 at 12:21
  • you wrote this [code] Number.prototype.mod = function(n) { var m = ((this%n)+n)%n; return m < 0 ? m + Math.abs(n) : m; }; [/code] give me one value of n where m is négative. they are no value of n where m is négative because you add n after the first % . – bormat May 07 '16 at 14:47
  • Without this check, `parseInt(-41).mod(-7)` would return `-6` instead of `1` (and this is exactly the purpose of the Integer part function I wrote) – zessx May 07 '16 at 19:30
  • ha ok, you re right, all my apologies, I forgot negative modulo, I was only thinking about the "this" negative. Can I suggest to move the Math.abs Number.prototype.mod = function(n) { return ((this%n)+ Math.abs(n))%n; }; (-41).mod(-7) == 1 //no need parseInt – bormat May 07 '16 at 19:45
  • 1
    You can simplify your function by removing the second modulo Number.prototype.mod = function(n) { var m = this%n; return (m < 0) ? m + Math.abs(n) : m; }; – bormat May 07 '16 at 20:07
  • Thx, PureScript Euclidian implementation is similar https://github.com/purescript/purescript-prelude/blob/ac720e443b3cf38e47048a3b1ab64c0dd2663d83/src/Data/EuclideanRing.js#L16 exports.intMod = function (x) { return function (y) { if (y === 0) return 0; var yy = Math.abs(y); return ((x % yy) + yy) % yy; }; }; might give some insights. – Coding Edgar Feb 05 '22 at 17:34
  • @[Gust van de Wal] Please do not edit answers' code without ensuring your code (1) works and (2) give the same result. Your edit (after fixing a typo) returned `6 0 0 6` instead of `6 1 1 6`. – zessx Mar 04 '22 at 13:08
2

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;
}
JayCrossler
  • 2,079
  • 2
  • 22
  • 22
1

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); 
    }
bormat
  • 1,309
  • 12
  • 16
0

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

maartenpaauw
  • 555
  • 2
  • 7
  • 20
0

For fun, here's a "wrap" function that works sorta like a modulo, except you can also specify the minimum value of the range (instead of it being 0):

const wrap = (value = 0, min = 0, max = 10) =>
  ((((value - min) % (max - min)) + (max - min)) % (max - min)) + min;

Basically just takes the true modulo formula, offsets it such that min ends up at 0, then adds min back in after.

Useful if you have a value that you want to keep between two values.

V. Rubinetti
  • 1,324
  • 13
  • 21