395

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

According to JavaScript, it is -13.

console.log(-13 % 64);

How do I fix this?

4
  • 4
    essentially a duplicate of How does java do modulus calculations with negative numbers? even though this is a javascript question. Commented Dec 18, 2010 at 0:22
  • 30
    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. Commented May 4, 2017 at 20:59
  • 3
    Which one did you mean to fix, Google or JS? Commented Apr 15, 2019 at 19:22
  • 7
    Why do nearly no languages implement modulo, given how useful it is? Commented Jan 14, 2021 at 8:39

15 Answers 15

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

Taken from this article: The JavaScript Modulo Bug

Sign up to request clarification or add additional context in comments.

21 Comments

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 covers it pretty well.
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.
Why take the modulo before adding n? Why not just add n and then take the modulo?
@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.
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.
|
266

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..

10 Comments

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): jsperf.com/negative-modulo/3
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.
I think you've got your ns and ms around the wrong way in your second example @StuR . It should be return ((n % m) + m) % m;.
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.
@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. stackoverflow.com/questions/6223449/…
|
42

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

6 Comments

It should be called the remainder operator but it is called modulus operator: developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/…
@DaveKennedy: MDN is not an official language reference, it's a community-edited site which sometimes gets it wrong. The spec 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."
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: en.wikipedia.org/wiki/Euclidean_division
@Ahmad—it's now called a multiplicative operator.
"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).
|
23

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

3 Comments

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: LOL! It does. An error by the HTML editor. The spec text does not.
The condition should be remain * m >= 0 ? remain : remain + m otherwise it doesn't work for negative divisors. For example, mod(-3, -18) returned -21 instead of -3. Pretty rare occurence but it just happened to break for me, years later.
15

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

9 Comments

If javascript changed the modulo operator to match the mathematical definition, the accepted answer would still work.
"What if Javascript changes the behavior in the future?" - Why would it? Changing the behaviour of such a fundamental operator is not likely.
+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.
@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.
What if the behavior of -, *, /, ;, ., (, ), ,, Math.floor, function or return changes? Then your code is horribly broken.
|
13

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)

Comments

9

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 

1 Comment

I mean if n is already a positive power of 2, wouldn't (1 << 6) - 13 be simpler, since -13 & (64 - 1) is really -13 & ((1 << 6) - 1)
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.

Comments

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

8 Comments

In euclidian function checking m < 0 is useless because ((this%n)+n)%n is always positive
@bormat Yes it is, but in Javascript % can return negative results (an this is the purpose of these functions, to fix it)
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 % .
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)
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; };
|
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;
}

Comments

2

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.

1 Comment

@V. Rubinetti : maybe also add some safeguard check in case user input for min and max happen to be the same (which would inadvertently trigger division by zero)
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); 
    }

Comments

1

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

Comments

0

Spotted. Fixed by using ternary operator:

var x = number % 12;
x = (x < 0)?(12+x):x;

Comments

-1

Assuming the language you're working with uses truncated division algorithm, this function will simultaneously return the modulo values for truncated division, floored division, and also Euclidean division (plus safe handling of division by zero).

The main advantage of this function is that only one single division is performed to obtain all 3 values, thus avoiding the double-work approach suggested by Mozilla MDN :

((n % d) + d) % d

(Arguments are auto integer truncated, so a divisor of -0.31 has same effect as division by zero)

function triple_mod(___, __, _, ____) {

    return sprintf("T:%+d_F:%+d_E:%+d", _ = (____ = (__ = int(__)) == (_ = \
                   !!__) || __ == -_ || (___ = int(___)) ==  __ || !___ ||
                   ! (_ = ___ % __)) ? (__ ? _ < _ : (_ = log(_)) - _) : _,
                   ___ = (____ || (!__ < __) - (___ < !__)) ? _ : _ + __,
                         (____ ||  !_ < _) ? _ : _ < +___ ? ___ : _ - __)
}

+9007199254738183 +61277761 T:+38898571_F:+38898571_E:+38898571
+9007199254738183 -61277761 T:+38898571_F:-22379190_E:+38898571

-9007199254738183 +61277761 T:-38898571_F:+22379190_E:+22379190
-9007199254738183 -61277761 T:-38898571_F:-38898571_E:+22379190

+4688888899996789   +131071 T:+80187_F:+80187_E:+80187
+4688888899996789   -131071 T:+80187_F:-50884_E:+80187

-4688888899996789   +131071 T:-80187_F:+50884_E:+50884
-4688888899996789   -131071 T:-80187_F:-80187_E:+50884

The function has no declared types because it's truly polymorphic - it accepts integers, floats, and even ASCII numeric strings.

The function contains no hardcoded numbers at all since all the necessary constants and thresholds are derived on the fly. Rapid handling logic exists for matching inputs, zero-dividend, divisor of ±1, and remainder-less exact division.

All calls to abs(), ceil(), or floor() type functions have been eliminated since the emulated value for Euclidean div benefits from floored-div performing most of the heavy lifting on its behalf.

The call to natural log function "(_ = log(_)) - _" is for obtaining a proper IEEE-754 NaN derived from log(0) - log(0) := (-inf) - (-inf)

So while this function isn't exactly Javascript per se, it's generic enough it should easily be portable to any language.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.