# RE: Integer division, surprising results

Discussion in 'Python' started by Tim Peters, May 10, 2004.

1. ### Tim PetersGuest

[Michael Cornelius]
> As an old C programmer, I'm surprised by some results I'm getting with
> integer division. For example:
>
> >>> -1/1000

> -1

As an old C programmer, you should have known that the C standard (C89)
didn't define whether the result here was -1 or 0.

> >>> -9/2

> -5

Likewise C didn't define whether this was -5 or -4.

> I expect the results of these expressions to be 0 and -4,
> respectively.

Most C compilers do generate code to return those.

> I've looked at faqs and documentation, and nothing jumped out at me.
> Can anyone explain the reasoning for this?

It's primarily driven by the desire that i%j have the same sign as j. If
you want that, and also want

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

then integer division has to return the floor. C also requres that identity
to hold, and then compilers that truncate i/j need to make i%j have the same
sign as i.

There are few real use cases for i%j when j is negative. When j is
positive, there are many, and in virually all of them it's more useful for
i%j to be >= 0 (if the clock says 10 now, what did it say 200 hours
go? -190 % 12 == 2 is useful; -190 % 12 == -10 is a bug waiting to bite).

Tim Peters, May 10, 2004

2. ### Ralf MuschallGuest

"Tim Peters" <> writes:

> It's primarily driven by the desire that i%j have the same sign as j. If

That's the side effect, not the desire (AFAIK).

> you want that, and also want
>
> i == (i/j)*j + (i%j)
>
> then integer division has to return the floor. C also requres that identity

AFAIK the history is the other way around: The Unix+C-philosophy was
essentially the "don't care"-approach, i.e. '/' does just what the CPU
happens to do if it sees a divide instruction. Most machines seem to
truncate here, therefore '%' can give negative results. This rarely
disturbs anyone, since most people don't divide negative numbers.
Those who do (e.g. mathematicians) fall outside the "good for 90% is
good enough"-attitude and have to help themselves.

Scheme and Lisp *do* care (offering both "remainder" (the easily
implemented thing) and "modulo" (the real thing)), as does Python with
its '%'[1]. (Called "rem" and "mod" in Lisp).

[1] I don't know whether it also offers a shortcut for
sign(x)*mod(abs(x),y) for people who insist on the bad result.

Ralf
--
GS d->? s:++>+++ a+ C++++ UL+++ UH++ P++ L++ E+++ W- N++ o-- K- w--- !O M- V-
PS+>++ PE Y+>++ PGP+ !t !5 !X !R !tv b+++ DI+++ D? G+ e++++ h+ r? y?

Ralf Muschall, May 12, 2004