The behaviour of integer division and modulo operations are explained in an article of The History of Python, namely: Why Python's Integer Division Floors . I'll quote the relevant parts:
if one of the operands is negative, the result is floored, i.e.,
rounded away from zero (towards negative infinity):
>>> -5//2
-3
>>> 5//-2
-3
This disturbs some people, but there is a good mathematical reason.
The integer division operation (//
) and its sibling, the modulo
operation (%
), go together and satisfy a nice mathematical
relationship (all variables are integers):
a/b = q
with remainder r
such that
b*q + r = a
and 0 <= r < b
(assuming a
and b
are >= 0
).
If you want the relationship to extend for negative a
(keeping b
positive), you have two choices: if you truncate q
towards zero, r
will become negative, so that the invariant changes to 0 <= abs(r)
otherwise, you can floor q
towards negative infinity, and the
invariant remains 0 <= r < b
.
In mathematical number theory, mathematicians always prefer the latter
choice (see e.g. Wikipedia). For Python, I made the same choice
because there are some interesting applications of the modulo
operation where the sign of a is uninteresting.
[...]
For negative b, by the way, everything just flips, and the invariant
becomes:
0 >= r > b.
In other words python decided to break the euclidean definition in certain circumstances to obtain a better behaviour in the interesting cases. In particular negative a
was considered interesting while negative b
was not considered as such. This is a completely arbitrary choice, which is not shared between languages.
Note that many common programming languages (C,C++,Java,...) do not satisfy the euclidean invariant, often in more cases than python (e.g. even when b
is positive).
some of them don't even provide any guarantee about the sign of the remainder, leaving that detail as implementation defined.
As a side note: Haskell provides both kind of moduluses and divisions. The standard euclidean modulus and division are called rem
and quot
, while the floored division and "python style" modulus are called mod
and div
.