10

Is there any remainder operator in Python? I do not ask for modulo operator, but remainder. For example:

-5 mod 2 = 1

but

-5 rem 2 = -1 # where "rem" is a remainder operator.

Do I have to implement it by myself ;)?

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
Dejwi
  • 4,393
  • 12
  • 45
  • 74
  • 3
    Yes, you have to implement it yourself. – Katriel Aug 28 '13 at 22:42
  • possible duplicate of [Find the division remainder of a number](http://stackoverflow.com/questions/5584586/find-the-division-remainder-of-a-number) – alecxe Aug 28 '13 at 22:42
  • @katrielalex but programming is hard :( – blakev Aug 28 '13 at 22:47
  • Do you really just want a truncated-division remainder, without having truncated division as well? – abarnert Aug 28 '13 at 22:52
  • 1
    "I do not ask for modulo operator, but remainder." You do understand those are the same things? See Wikipedia: "In computing, the modulo (sometimes called modulus) operation finds the remainder of division of one number by another." (Or do you just want different rules about negatives?) – Thanatos Aug 28 '13 at 22:52
  • http://stackoverflow.com/questions/339719/when-is-the-difference-between-quotrem-and-divmod-useful – Josh Lee Aug 28 '13 at 22:57
  • @alecxe: This is not a dup. The OP here already knows how to get the floor-to-neg-inf remainder in Python, and wants to know how to get the truncate-to-0 remainder instead. So, a question whose answer is the `%` operator isn't very helpful. – abarnert Aug 28 '13 at 23:03
  • @Thanatos Ok, I'm more familiar with C++ and I would like to have remainder operator like in C++ language ;). Where -7 % 4 is equal -3. In Python it would be 1. – Dejwi Aug 29 '13 at 06:30
  • @Dejwi: Actually, C++ leaves it up to the implementation to use any of the three remainder algorithms for `%`. (C99 did finally specify one, and I believe C++11 inherits that choice by incorporation of the relevant part of the C99 spec… but earlier versions of C++ definitely do not.) So, unless you've learned C++ very recently, if you've been relying on `-7 % 4 == -3`, your code wasn't portable. – abarnert Aug 29 '13 at 17:34
  • @abarnert I'm pretty sure, that this is how it works on GCC na MSVCP. Thank you, I didn't know it is implementation specific. – Dejwi Aug 29 '13 at 18:45
  • @Dejwi: Well, that's exactly how you run into problems with implementation-specific stuff: you test it on GCC on one platform and MSVC on another and assume that if they agree, it's portable… (Well, maybe not you specifically, but I personally have created hard-to-track-down bugs that I had to fix 3 years after forgetting the code that way…) – abarnert Aug 29 '13 at 19:15

3 Answers3

24

There are actually three different definitions of "modulo" or "remainder", not two:

  • Truncated division remainder: sign is the same as the dividend.
  • Floored division remainder: sign is the same as the divisor.
  • Euclidean division remainder: sign is always positive.

Calling one of them "modulo" and another "remainder" is very confusing; all three of them are useful definitions for both terms.

Almost every language only provides one of the three (Fortran being a notable exception).* Most languages provide the one that matches the language's division operator.** Because Python uses floored division (following Knuth's argument in The Art of Computer Programming), it uses the matching remainder operator.

If you want either of the other, you have to write it manually. It's not very hard; this Wikipedia article shows how to implement all three.

For example:

def trunc_divmod(a, b):
    q = a / b
    q = -int(-q) if q<0 else int(q)
    r = a - b * q
    return q, r

Now, for your example:

>>> q, r = trunc_divmod(-5, 2)
>>> print(q, r)
-2 -1

* Often languages that provide both call truncated remainder some variation on mod, and floored some variation on rem… but that definitely isn't something to rely on. For example, Fortran calls floored remainder modulo, while Scheme calls Euclidean remainder mod.

** Two notable exceptions are C90 and C++03, which leave the choice up to the implementation. While many implementations use truncated division and remainder, some do not (a few even use truncated division and floored remainder, which means a = b * (a/b) + a%b does not even work…).

abarnert
  • 354,177
  • 51
  • 601
  • 671
1

Edit: it's not entirely clear what you meant when you were asking for a remainder operation, the way to do this will depend on what requirements there are on the sign of the output.

If the sign is to be always positive divmod can do what you want, it's in the standard library

http://docs.python.org/2/library/functions.html#divmod

Also you might want to look at the built-in binary arithmetic operators:

http://docs.python.org/2/reference/expressions.html

If the remainder has to have the same sign as the the argument passed then you'd have to roll your own such as this:

import math
def rem(x,y):
    res = x % y
    return math.copysign(res,x)
shuttle87
  • 15,466
  • 11
  • 77
  • 106
  • 2
    No, `divmod(a, b)` returns the exact same thing as `(a/b, a%b)`. In other words, the OP will still get `1` rather than `-1` as he wants. – abarnert Aug 28 '13 at 22:44
  • Clearly "if the sign is to be always positive" doesn't help, because it's not true of the only example the OP gives us, `-5 rem 2 = -1`. – abarnert Aug 28 '13 at 23:04
  • The new version is completely broken—try it with `rem(-5, -2)`. – abarnert Aug 29 '13 at 17:50
  • This post needs correction still. "If the sign is to be always positive divmod can do [it]" is incorrect. The sign of the remainder is the same as the sign of the divisor. – sfkleach Oct 24 '22 at 11:18
0

Does math.fmod do what you're looking for?

Chris Wesseling
  • 6,226
  • 2
  • 36
  • 72
  • 1
    No, `fmod` returns the result "as defined by the platform C library". Which type of remainder that means is implementation-dependent. (C99 _does_ define one, but at least Python 2.7 is written in C90, not C99.) So, this _may_ do what he's looking for on his platform… and then do something different on another platform. (There's also the fact that `fmod` converts everything to `float`, and the docs explicitly say that it's not preferred when working with integers.) – abarnert Aug 29 '13 at 17:37