75

I have found that the same mod operation produces different results depending on what language is being used.

In Python:

-1 % 10

produces 9

In C it produces -1 !

  1. Which one is the right modulo?
  2. How to make mod operation in C to be the same like in Python?
Cristian Ciupitu
  • 20,270
  • 7
  • 50
  • 76
psihodelia
  • 29,566
  • 35
  • 108
  • 157

6 Answers6

89
  1. Both variants are correct, however in mathematics (number theory in particular), Python's modulo is most commonly used.
  2. In C, you do ((n % M) + M) % M to get the same result as in Python. E. g. ((-1 % 10) + 10) % 10. Note, how it still works for positive integers: ((17 % 10) + 10) % 10 == 17 % 10, as well as for both variants of C implementations (positive or negative remainder).
Alex B
  • 82,554
  • 44
  • 203
  • 280
  • 3
    What aout n = - 11? I think you meant ((n % M) + M) % M – Henrik Dec 15 '09 at 13:51
  • with (-17 + 10) % 10 you are in the same problem. – yeyeyerman Dec 15 '09 at 13:52
  • 3
    I must disagree with point 1, and say that in mathematics both are correct, as it defines a congruence class. – SurDin Dec 15 '09 at 14:03
  • @Checkers not so right, in C it doesn't define a true congruence relationship since -1 % 10 != 9 % 10 and they are obviously in the same congruence class. – fortran Dec 15 '09 at 14:23
  • @fortran That's why in C you have to roll your own implementation that does define one, no? – Alex B Dec 15 '09 at 14:28
  • @Checkers I guess so... but my discrete mathematics days seem so far away now – fortran Dec 15 '09 at 14:34
  • If I'm understanding this, the two operations are only different when one operand is negative and the other isn't. Is that right? – Justin Morgan - On strike Feb 07 '14 at 16:52
  • @AlexB I disagree that Python's % operation is the commonly-used or 'true' modulo operation. As far as I know, Number Theory uses Euclidean division, which requires **r>0**. So neither of these two % operation is the commonly-used modulo operation. – Rick Nov 09 '17 at 08:55
39

Python has a "true" modulo operation, while C has a remainder operation.

It has a direct relation with how the negative integer division is handled, i.e. rounded towards 0 or minus infinite. Python rounds towards minus infinite and C(99) towards 0, but in both languages (n/m)*m + n%m == n, so the % operator must compensate in the correct direction.

Ada is more explicit and has both, as mod and rem.

fortran
  • 74,053
  • 25
  • 135
  • 175
  • @Svante, It's easy to implement both in a library. – Pacerier Sep 10 '14 at 09:33
  • @Pacerier: yes, that's a form of greenspunning. Modulo and remainder are also very low level operations, so it is not trivial to ensure efficiency from a high level library. – Svante Sep 10 '14 at 10:04
  • @Svante, Greenspunning is part and parcel of life. It even exists in Common Lisp, except the *color* is no longer green. – Pacerier Sep 10 '14 at 10:28
  • Python modulo is not exactly "true" modulo, because it allows M < 0 – mykhal Jun 01 '15 at 10:46
17

In C89/90 the behavior of division operator and remainder operator with negative operands is implementation-defined, meaning that depending on the implementation you can get either behavior. It is just required that the operators agree with each other: from a / b = q and a % b = r follows a = b * q + r. Use static asserts in your code to check the behavior, if it relies critically on the result.

In C99 the behavior you observe has become standard.

In fact, either behaviors have certain logic in it. The Python's behavior implements the true modulo operation. The behavior you observed is C is consistent with rounding towards 0 (it's also Fortran behavior).

One of the reasons the rounding towards 0 is preferred in C is that it is rather natural to expect the result of -a / b be the same as -(a / b). In case of true modulo behavior, -1 % 10 would evaluate to 9, meaning that -1 / 10 has to be -1. This might be seen as rather unnatural, since -(1 / 10) is 0.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 2
    Whole-number division is periodic; (a+kb)/b = (a/b)+k. Real-number division is periodic and symmetric. Trying to define integer division so as to add symmetry will make it cease to be periodic unless the divisor is odd and it is computed using round-to-nearest semantics. I would regard periodicity as more important than symmetry, though others may differ. – supercat Sep 26 '14 at 19:21
5

Both answers are correct since -1 modulo 10 is the same as 9 modulo 10.

r = (a mod m)
a = n*q + r

You can be sure that |r| < |n|, but not what the value of r is. There are 2 answers, negative and positive.


In C89, although the answer will always be correct, the exact value of a modulo operation (they refer to it as remainder) is undefined, meaning it can be either a negative result or a positive result. In C99 the result is defined.

If you want the positive answer though, you can simply add 10 if you find your answer is negative.

To get the modulo operator to work the same on all languages, just remember that:

n mod M == (n + M) mod M

and in general:

n mod M == (n + X * M) mod M
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
  • 7
    Modulo of negative numbers in C **is** defined: by the following statement: *If the quotient `a/b` is representable, the expression `(a/b)*b + a%b` shall equal `a`.* – caf Dec 15 '09 at 14:04
  • 5
    (I should add that in C `%` isn't actually defined as a "modulo" operator - it's defined as a "remainder"). – caf Dec 15 '09 at 14:06
  • 1
    It seems so, I was going by this wikipedia page which states that it is not defined in C89: http://en.wikipedia.org/wiki/Modulo_operation – Brian R. Bondy Dec 15 '09 at 14:14
  • 1
    its implementaion defined i.e. its either -1 or 9 but has to be one of them – jk. Dec 15 '09 at 14:15
  • @ Brian / jk: Incorrect answer. The current standard for C is C99, not C89, and C99 does define the *remainder* operator quite well, as the Wikipedia site Brian linked does state quite clearly. – DevSolar Dec 15 '09 at 14:58
  • @DevSolar: Of course C89 is not the current standard. I just assumed (wrongly so apparently) that this aspect didn't change from C89. I re-modified my answer – Brian R. Bondy Dec 15 '09 at 15:10
5

Performing Euclidean division a = b*q + r, is like rounding the fraction a/b to an integer quotient q, and then compute the remainder r.

The different results you see depends on the convention used for rounding the quotient...

If you round toward zero (truncate), you will get a symmetry around zero like in C:

truncate(7/3) = 2
7 = 3*2 + 1

truncate(-7/3) = -2
-7 = 3* -2 - 1

truncate(7/-3) = -2
7 = -3* -2 + 1

If you round toward negative infinity (floor), you will get a remainder like in Python:

floor(7/3) = 2
7 = 3*2 + 1

floor(-7/3) = -3
-7 = 3* -3 + 2

floor(7/-3) = -3
7 = -3* -3 - 2

If you round to nearest int (tie to whatever you want, to even, or away from zero) you'll get a centered modulo:

round(7/3) = 2
7 = 3*2 + 1

round(8/3) = 3
8 = 3*3 - 1

round(-7/3) = -2
-7 = 3* -2 - 1

round(7/-3) = -2
7 = -3* -2 + 1

You could try to implement your own modulo with rounding toward positive infinity (ceil), and you would invent a rather unconventional modulo, but it would still be kind of modulo...

aka.nice
  • 9,100
  • 1
  • 28
  • 40
1

Since python 3.7 you can also use .remainder() from math built-in module.

Python 3.7.0a0 (heads/master:f34c685020, May  8 2017, 15:35:30)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> math.remainder(-1, 10)
-1.0

From docs:

Return the IEEE 754-style remainder of x with respect to y. For finite x and finite nonzero y, this is the difference x - n*y, where n is the closest integer to the exact value of the quotient x / y. If x / y is exactly halfway between two consecutive integers, the nearest even integer is used for n. The remainder r = remainder(x, y) thus always satisfies abs(r) <= 0.5 * abs(y).

Special cases follow IEEE 754: in particular, remainder(x, math.inf) is x for any finite x, and remainder(x, 0) and remainder(math.inf, x) raise ValueError for any non-NaN x. If the result of the remainder operation is zero, that zero will have the same sign as x.

On platforms using IEEE 754 binary floating-point, the result of this operation is always exactly representable: no rounding error is introduced.

Community
  • 1
  • 1
vishes_shell
  • 22,409
  • 6
  • 71
  • 81
  • 1
    This doesn't answer neither part of the question. – Yola Apr 05 '19 at 19:15
  • 1
    @Yola You are technically correct, but this answer adds value to the thread. I would also argue that just asking `How to make mod operation in C to be the same like in Python?` is unnecessarily one-sided and should really include the `How to make Python behave like C` as well. – Turun Jun 03 '21 at 12:14