3

In JavaScript the % operator seems to behave in a very weird manner. I tried the following:

>>> (0 - 11) % 12
-11

Why does it return -11 instead of 1 (as in Python)?

I am sure I am doing or expecting something wrong, but the docs don't tell me what.

Baishampayan Ghose
  • 19,928
  • 10
  • 56
  • 60

5 Answers5

7

It's behaving correctly according to the way the language is specified (e.g. ECMA 262), where it's called the remainder operator rather than the modulus operator. From the spec:

The result of an ECMAScript floating-point remainder operation is determined by the rules of IEEE arithmetic:

  • If either operand is NaN, the result is NaN.
  • The sign of the result equals the sign of the dividend.
  • If the dividend is an infinity, or the divisor is a zero, or both, the result is NaN.
  • If the dividend is finite and the divisor is an infinity, the result equals the dividend.
  • If the dividend is a zero and the divisor is nonzero and finite, the result is the same as the dividend.
  • In the remaining cases, 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 computed and rounded to the nearest representable value using IEEE 754 round-to-nearest mode.

In your case n/d is negative, so the result is negative.

See the Wikipedia entry on modulo for more details, including a list of languages with the behaviour in terms of the sign of the result.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

There are two similar operations: modulo and remainder. Modulo represents a more mathematical usage, and remainder more IT usage.

Assume we have two integers, a and b.

MOD(a, b) will return a result which has the same sign as b.

REM(a, b) will return a result which has the same sign as a. - this is what is implemented in C/C++/C# as the % operator and often confusingly called "mod"

You can think of it like this too:

MOD(a, b) will find the largest integer multiple of b (call it "c") that is smaller than a, and return (a - c).

e.g. MOD(-340,60) we find c = -360 is the largest multiple of 60 that is smaller than -340. So we do (-340 - (-360)) = 20.

REM(a, b) will return a value such that (DIV(a,b) * b) + REM(a, b) = a, where DIV() represents integer division.

So for r = REM(-340, 60)

-340 = DIV(-340,60) * 60 + r = -5 * 60 + r = r - 300

This solves to give us r = -40.

0

You say MOD(a,b) will return a result with the same sign as b, but then say that it returns (a-c) where c is smaller than a. This second definition means that it always returns a positive number. Which is it?

0

-11 < 12, so i 'suppose' they don't actually divide: So -11 = 0x12 -11

Have a try with (0-13) % 12

Aif
  • 11,015
  • 1
  • 30
  • 44
-1

fmod from the math module behaves correctly in python:

>>> from math import *
>>> fmod(-11, 12)
-11.0

-11 is the correct answer..

rejj
  • 152
  • 2
  • 1
    "Correct" depends on how you define modulus though. I suspect the JavaScript implementation is correct by their definition too. Follow the link in my answer - the issue isn't as clear as you might expect. – Jon Skeet Jan 17 '09 at 12:13