Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Modulo operator : differences between C and Python

57 views
Skip to first unread message

Erik de Castro Lopo

unread,
Mar 10, 2002, 5:59:03 PM3/10/02
to
Hi all,

Just recently I prototyped a relatively complex algorithm in Python
before converting it to C. During this conversion I noticed that
the modulo operator returns different results in C and Python if
the numerator is negative. For positive values they produce the same
result.

----------------------------------------------------------------
erikd@coltrane > python
Python 2.1.2 (#1, Jan 18 2002, 18:05:45)
[GCC 2.95.4 (Debian prerelease)] on linux2
Type "copyright", "credits" or "license" for more information.
>>> 123 % 12
3
>>> -123 % 12
9
>>>
erikd@coltrane > cat mod_test.c
#include <stdio.h>

int main (void)
{ int a = 123 ;

printf (" % d %% 12 == %d\n", a, a % 12) ;
printf (" % d %% 12 == %d\n", -a, -a % 12) ;
return 0 ;
}
erikd@coltrane > gcc -Wall mod_test.c -o mod_test
erikd@coltrane > ./mod_test
123 % 12 == 3
-123 % 12 == -3
----------------------------------------------------------------

Anybody have any idea why this is?

Erik
--
+-----------------------------------------------------------+
Erik de Castro Lopo nos...@mega-nerd.com (Yes it's valid)
+-----------------------------------------------------------+
The government everybody loves to abuse sues the company everybody loves
to hate. Throw in a bunch of faceless lawyers cross-examining techies
[with] all the charisma of a video driver and you've got a spectacle of
thoroughly miniscule proportions.

Tim Peters

unread,
Mar 10, 2002, 6:37:37 PM3/10/02
to
[Erik de Castro Lopo]

> Just recently I prototyped a relatively complex algorithm in Python
> before converting it to C. During this conversion I noticed that
> the modulo operator returns different results in C and Python if
> the numerator is negative. For positive values they produce the same
> result.

Python defines the result of i%j to have the same sign as j; what C requires
depends on which year's C standard you're looking at (it was left up to
implementers' discretion before the 1999 standard); the C implementations I
use return a result with i's sign, and I usually curse them for that.

Note that this is related to what "i/j" returns. Both languages preserve

i == (i/j)*j + i%j

in non-pathological cases (j != 0, etc).


Geoff Gerrietts

unread,
Mar 10, 2002, 6:07:01 PM3/10/02
to
Quoting Erik de Castro Lopo (nos...@mega-nerd.com):
> Just recently I prototyped a relatively complex algorithm in Python
> before converting it to C. During this conversion I noticed that
> the modulo operator returns different results in C and Python if
> the numerator is negative. For positive values they produce the same
> result.

I ran into this very same thing the other day. I was setting my
expectations of how a C expression would evaluate by testing it in the
python shell, only to discover that it evaluated quite differently.

I don't think it bothered me. Just surprised me. Turns out what I
really wanted was the Python answer anyway. I'm not sure the answer I
got in C is actually the modulo, if I understand the mathematical
concept "modulo" properly.

--
Geoff Gerrietts "I am always doing that which I can not do,
<geoff at gerrietts net> in order that I may learn how to do it."
http://www.gerrietts.net --Pablo Picasso

David Eppstein

unread,
Mar 10, 2002, 7:58:49 PM3/10/02
to
In article <3C8BE537...@mega-nerd.com>,

Erik de Castro Lopo <nos...@mega-nerd.com> wrote:

>
> Just recently I prototyped a relatively complex algorithm in Python
> before converting it to C. During this conversion I noticed that
> the modulo operator returns different results in C and Python if
> the numerator is negative. For positive values they produce the same
> result.

Yes. Python produces the correct results. C doesn't.

Almost every time I use modulo in C, I end up having to fix it by adding
the modulus if the result is negative.

--
David Eppstein UC Irvine Dept. of Information & Computer Science
epps...@ics.uci.edu http://www.ics.uci.edu/~eppstein/

Courageous

unread,
Mar 10, 2002, 9:38:06 PM3/10/02
to

>> Just recently I prototyped a relatively complex algorithm in Python
>> before converting it to C.

I'm curious about your experiences. I did something myself recently,
creating a fairly sophisticated prototype in Python and then implemented
it in C++. Given that I had all the algorithms worked out and thoroughly
debugged, it was astounding to me how difficult it was to get properly
translated and then validated. It took literally 3 times as long or longer
to get the C++ version implemented and provably functional, this in spite
of the design time work being included in what it took to do the Python
implementation.

Programming in C++ genuinely depresses me.

And I'm an old veteran. I've been using it since the days of C Front, if
anyone around happens to know what that means. :-)

C//

Erik de Castro Lopo

unread,
Mar 10, 2002, 10:01:54 PM3/10/02
to
Courageous wrote:
>
> >> Just recently I prototyped a relatively complex algorithm in Python
> >> before converting it to C.
>
> I'm curious about your experiences. I did something myself recently,
> creating a fairly sophisticated prototype in Python and then implemented
> it in C++. Given that I had all the algorithms worked out and thoroughly
> debugged, it was astounding to me how difficult it was to get properly
> translated and then validated. It took literally 3 times as long or longer
> to get the C++ version implemented and provably functional, this in spite
> of the design time work being included in what it took to do the Python
> implementation.

My experience was that once I had it working and validated in Python
converting to C was pretty trival. The validation I had done in Python
allowed me to find the problem in the C version pretty quickly. 80% of
the whole process was getting the Python code working.

> Programming in C++ genuinely depresses me.

Thats why I try to avoid C++ :-).

> And I'm an old veteran. I've been using it since the days of C Front, if
> anyone around happens to know what that means. :-)

I never used C Front but did spend a number of years (1990-1995) where
C++ was my main language. Nowadays I only use C++ when I really, REALLY
*REALLY* need C++ features. The rest is split between C and Python.

Erik
--
+-----------------------------------------------------------+
Erik de Castro Lopo nos...@mega-nerd.com (Yes it's valid)
+-----------------------------------------------------------+

"Only wimps use tape backup: *real* men just upload their
important stuff on FTP, and let the rest of the world
mirror it ;)" -- Linus Torvalds

Cimarron Taylor

unread,
Mar 10, 2002, 11:42:32 PM3/10/02
to
> Anybody have any idea why this is?
> Erik

I encountered this as well in an application which needed to
verify the results of a C program. Python seems to be counting
"down" from y if x<0. I simply compensated for this with
the following function:

def mod(x,y):
m = x%y
if m==0 or x>0: return m
return m-y

Another thing to watch out for when comparing results from Python and
C include is overflow/underflow behavior of the math operations.

Cim

John Machin

unread,
Mar 11, 2002, 1:00:02 AM3/11/02
to
Erik de Castro Lopo <nos...@mega-nerd.com> wrote in message news:<3C8BE537...@mega-nerd.com>...

> Hi all,
>
> Just recently I prototyped a relatively complex algorithm in Python
> before converting it to C. During this conversion I noticed that
> the modulo operator returns different results in C and Python if
> the numerator is negative. For positive values they produce the same
> result.
[snip]

> Anybody have any idea why this is?

The Python reference manual: "The modulo operator always yields a
result with the same sign as its second operand (or zero)"

K&R2, p. 205 says: [paraphrased] If both operands are non-negative,
then the remainder is non-negative and smaller than the divisor; if
not, it is guaranteed only that abs(remainder) < abs(divisor).

So what you see from C depends on the compiler and architecture. If
you are at all interested in portablity of your C code, you will need
to take precautions.

Why? Philosophy, I suppose: C gives you generally what the hardware
gives you. Python mostly gives you what is useful and consistent, even
if the implementation has to work a bit harder to do that.

There is also a lengthy thread in this newsgroup -- you can easily
find it by googling "modulo remainder negative".

<:-)>
BTW, speaking of "easily find", were you having simultaneous problems
with all of (1) the index in K&R (2) the Python reference manual (3)
Google???
</:-)>

Andrew Koenig

unread,
Mar 11, 2002, 12:49:02 AM3/11/02
to
jkraska> Programming in C++ genuinely depresses me.

jkraska> And I'm an old veteran. I've been using it since the days of
jkraska> C Front, if anyone around happens to know what that
jkraska> means. :-)

Unfortunately, there are lots of terrible C++ books out there.
The standard library has opened up lots of new doors that most
of the books simply ignore, which means that a lot of programmers
don't even know that they exist.

I don't want to start a C++ discussion on comp.lang.python,
but I'll be glad to continue this discussion on comp.lang.c++
if you like.

--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark

jcm

unread,
Mar 11, 2002, 8:04:51 AM3/11/02
to
A better name might be rem, as this produces the remainder of x/y.
Python returns what most would call the modulus.

Kragen Sitaker

unread,
Mar 19, 2002, 3:32:02 AM3/19/02
to
Tim Peters <tim...@comcast.net> writes:
> Python defines the result of i%j to have the same sign as j; what C requires
> depends on which year's C standard you're looking at (it was left up to
> implementers' discretion before the 1999 standard); the C implementations I
> use return a result with i's sign, and I usually curse them for that.

This is a result of C being a portable assembly language; % returns
whatever the underlying remainder register has after a divide, which
generally has i's sign.

0 new messages