问题描述:

I've found some strange behaviour in python regarding negative numbers:

`>>> a = -5`

>>> a % 4

3

Could anyone explain what's going on?

Unlike C or C++, Python's modulo operator (`%`

) always return a number having the same sign as the denominator (divisor). Your expression yields 3 because

(-5) % 4 = (-2 × 4 + 3) % 4 = 3.

It is chosen over the C behavior because a nonnegative result is often more useful. An example is to compute week days. If today is Tuesday (day #2), what is the week day *N* days before? In Python we can compute with

```
return (2 - N) % 7
```

but in C, if *N* ≥ 3, we get a negative number which is an invalid number, and we need to manually fix it up by adding 7:

```
int result = (2 - N) % 7;
return result < 0 ? result + 7 : result;
```

(See http://en.wikipedia.org/wiki/Modulo_operator for how the sign of result is determined for different languages.)

Here's an explanation from Guido van Rossum:

http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html

Essentially, it's so that a/b = q with remainder r preserves the relationships b*q + r = a and 0 <= r < b.

There is no one best way to handle integer division and mods with negative numbers. It would be nice if `a/b`

was the same magnitude and opposite sign of `(-a)/b`

. It would be nice if `a % b`

was indeed a modulo b. Since we really want `a == (a/b)*b + a%b`

, the first two are incompatible.

Which one to keep is a difficult question, and there are arguments for both sides. C and C++ round integer division towards zero (so `a/b == -((-a)/b)`

), and apparently Python doesn't.

Modulo, equivalence classes for 4:

- 0: 0, 4, 8, 12... and -4, -8, -12...
- 1: 1, 5, 9, 13... and -3, -7, -11...
- 2: 2, 6, 10... and -2, -6, -10...
- 3: 3, 7, 11... and -1, -5, -9...

Here's a link to modulo's behavior with negative numbers. (Yes, I googled it)

As pointed out, Python modulo makes a well-reasoned exception to the conventions of other languages. This gives negative numbers a seamless behavior, especially when used in combination with the `//`

integer-divide operator, as `%`

modulo often is (as in math.divmod):

```
for n in range(-8,8):
print n, n//4, n%4
```

Produces:

```
-8 -2 0
-7 -2 1
-6 -2 2
-5 -2 3
-4 -1 0
-3 -1 1
-2 -1 2
-1 -1 3
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3
```

I also thought it was a strange behavior of Python. It turns out that I was not solving the division well (on paper); I was giving a value of 0 to the quotient and a value of -5 to the remainder. Terrible... I forgot the geometric representation of integers numbers. By recalling the geometry of integers given by the number line, one can get the correct values for the quotient and the remainder, and check that Python's behavior is fine. (Although I assume that you have already resolved your concern a long time ago).

您可能感兴趣的文章：

- SQL Server 2005 derived field w/ logic
- Run command prompt from java?
- idiomatic - How do I return a clojure map with fixed keys and conditional values?
- php - Retrieve decimal data from mysql and put into an array
- c++ - Array C[]=A[]*B[] in high-performance calculation
- php - Reading a specific line from a text file
- clr - Any implementation of an Unrolled Linked List in C#?
- Finding Hudson Log Files
- Forward to a payment-gateway together with POST data using cURL (or any other PHP server side solution)
- WCF in Winforms app - is it always single-threaded?

随机阅读：

**推荐内容**-

**热点内容**-
- php - Reading a specific line from a text file
- clr - Any implementation of an Unrolled Linked List in C#?
- Finding Hudson Log Files
- Forward to a payment-gateway together with POST data using cURL (or any other PHP server side solution)
- WCF in Winforms app - is it always single-threaded?
- git svn - git svn fetch does not fetch a Subversion commit message modified after initial clone
- java me - Why I am getting the bad length exception when I am running this application?
- java - How to get string.format to complain at compile time
- ruby on rails - Trigger observer of parent class on change
- python - Issue with URL pattern in Django with webmonkey tutorial