I have been conducting a few tests in Javascript, I will show them (pasted from console):
-1 % 4
-1
-4 % 4
-0
-8 % 4
-0
-6 % 4
-2
-6 % -4
-2
6 % -4
2
-1 % 4 is truly -1, however, I do not really understand why is Javascript not yielding 3, which is equally correct, but more canonic.
What is -0? I know -4 / 4 = -1, which is an integer, but I am not sure what -0 is.
I am puzzled about Javascript's calculation of modulo.
My tests were motivated by a slightly unpleasant surprise that I have been working on a gallery and I have an index for the active picture. There are two buttons, for next and previous buttons. The next image of the last image is the first image and the previous image of the first image is the last image. I have been changing the index as:
currentImageIndex = (currentImageIndex + 1) % images.length;
when the user clicked on the next button. When the user clicked on the previous button, I have been trying with the following code:
currentImageIndex = (currentImageIndex - 1) % images.length;
I was surprised to see that the latter did not work well, as the previous image was not shown and an error was thrown as an invalid index was used in the array indexed by currentImageIndex. I have console.log-ed the value and have seen that it is -1! Ok, I have worked around the problem with:
currentImageIndex = (currentImageIndex + images.length - 1) % images.length
and it was not too painful, but still, I did not understand the logic behind the result of the calculation. So, is there somebody, who kows how Javascript's modulo calculation works, as I am really puzzled and I see -0 as a result of -4 % 4 to be the joke of the month.
I have been conducting a few tests in Javascript, I will show them (pasted from console):
-1 % 4
-1
-4 % 4
-0
-8 % 4
-0
-6 % 4
-2
-6 % -4
-2
6 % -4
2
-1 % 4 is truly -1, however, I do not really understand why is Javascript not yielding 3, which is equally correct, but more canonic.
What is -0? I know -4 / 4 = -1, which is an integer, but I am not sure what -0 is.
I am puzzled about Javascript's calculation of modulo.
My tests were motivated by a slightly unpleasant surprise that I have been working on a gallery and I have an index for the active picture. There are two buttons, for next and previous buttons. The next image of the last image is the first image and the previous image of the first image is the last image. I have been changing the index as:
currentImageIndex = (currentImageIndex + 1) % images.length;
when the user clicked on the next button. When the user clicked on the previous button, I have been trying with the following code:
currentImageIndex = (currentImageIndex - 1) % images.length;
I was surprised to see that the latter did not work well, as the previous image was not shown and an error was thrown as an invalid index was used in the array indexed by currentImageIndex. I have console.log-ed the value and have seen that it is -1! Ok, I have worked around the problem with:
currentImageIndex = (currentImageIndex + images.length - 1) % images.length
and it was not too painful, but still, I did not understand the logic behind the result of the calculation. So, is there somebody, who kows how Javascript's modulo calculation works, as I am really puzzled and I see -0 as a result of -4 % 4 to be the joke of the month.
Share Improve this question asked Jun 5, 2014 at 0:44 Lajos ArpadLajos Arpad 77.4k40 gold badges117 silver badges222 bronze badges 20- ( -0 === 0 && -0 == 0 ) === true, so why's it matter – Cory Danielson Commented Jun 5, 2014 at 0:49
-
2
But
(1/-0 === 1/0) is false
, so it does. – 000 Commented Jun 5, 2014 at 0:51 - 3 possible duplicate of Javascript modulo not behaving – Tom Panning Commented Jun 5, 2014 at 0:54
- 1 It's explained in the docs, it's a binary operator that returns the integer remainder of dividing the two operands, so it's not a true euclidean modulo. – adeneo Commented Jun 5, 2014 at 0:56
- 1 Have you tried the spec? – RobG Commented Jun 5, 2014 at 0:57
4 Answers
Reset to default 4Great question!
It seems to me that ECMA is confusing and it's easy to miss how the modulo operator works (I certainly did). From ECMA-262 §11.5.3 there is a statement that:
The result of a floating-point remainder operation as puted by the % operator…
which infers a remainder operation. It goes on to provide an algorithm:
…where neither an infinity, nor a zero, nor NaN is involved, the floating-point remainder r from a dividend n and a divisor d is defined by the mathematical relation r = n − (d × q) where q is an integer that is negative only if n/d is negative and positive only if n/d is positive, and whose magnitude is as large as possible without exceeding the magnitude of the true mathematical quotient of n and d. r is puted and rounded to the nearest representable value using IEEE 754 round-to-nearest mode.
Applying that to the case of -1 % 4
, then:
n = -1
d = 4
trueMathematicalQuotient = -1/4 = -0.25
Therefore q
must be negative since n/d
is negative. The largest negative integer that d (4) can be multiplied by that is less than or equal to -0.25 in magnitude and that the gives a result less than or equal to n (-1) is -0 (noting that -1 has greater magnitude than -0.25).
The simple way to do that is to truncate q to an integer:
q = -0 // -0.25 truncated
Putting numbers into the equation:
r = -1 - (4 * 0)
r = -1 - 0
r = -1
Which can be put in a function as:
function remainderMod(n, d) {
var q = parseInt(n / d); // truncates to lower magnitude
return n - (d * q);
}
or abbreviated to:
function remainderMod(n, d) {
return n - (d * (n/d | 0));
}
The OP wanted to understand what is going on (not necessarily "fix" it). The short answer is that JavaScript has a "remainder" operator not a "modulo" operator (according to Douglas Crawford). For the full difference, here is a description of modulo vs remainder (specifically referring to C#).
Edit: Finally, the spec has the definitive answer.
Have a look at this question, and this answer which has a solution for you.
The problem you're running into is that JavaScript's %
operator is not a true modulo, but rather a simple remainder.
In the case that the above link breaks, here is the solution:
Number.prototype.mod = function(n) {
return ((this%n)+n)%n;
}
This can be used like this:
(-1).mod(4); // returns 3
If you don't want to alter the prototype of Number
you can instead just make a function:
function modulo(a, b) {
return ((a % b) + b) % b
}
Which can be used like this:
modulo(-1, 4); // returns 3
Modulo Function is a remainder. So 10 % 4 means "Divide 10 by 4 and return the remainder" When the remainder is 0 you know that that it is perfectly divisible. So -6 % 4 = -4. This happens because Javascript sees the -6 as a non existant number, or another type of 0, so you are left with that negative number after it divides it by the whole number 0 times. It is is known bug.