web-dev-qa-db-de.com

Die Modulo-Operation für negative Zahlen in Python

Ich habe in Python bezüglich negativer Zahlen ein seltsames Verhalten festgestellt:

>>> -5 % 4
3

Könnte jemand erklären, was los ist?

59
facha

Im Gegensatz zu C oder C++ ist Pythons Modulo-Operator (%) Gebe immer eine Zahl mit dem gleichen Vorzeichen wie der Nenner (Divisor) zurück. Dein Ausdruck ergibt 3 weil

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

Es wird dem C-Verhalten vorgezogen, da ein nichtnegatives Ergebnis oft nützlicher ist. Ein Beispiel ist die Berechnung von Wochentagen. Wenn heute Dienstag (Tag Nr. 2) ist, was ist der Wochentag [~ # ~] n [~ # ~] Tage zuvor? In Python können wir mit

return (2 - N) % 7

aber in C, wenn [~ # ~] n [~ # ~] ≥ 3, erhalten wir eine negative Zahl, die eine ungültige Zahl ist, und wir Sie müssen das Problem manuell beheben, indem Sie 7 hinzufügen:

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

(Siehe http://en.wikipedia.org/wiki/Modulo_operator wie das Vorzeichen des Ergebnisses für verschiedene Sprachen bestimmt wird.)

95
kennytm

Hier ist eine Erklärung von Guido van Rossum:

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

Im Wesentlichen ist es so, dass a/b = q mit dem Rest r die Beziehungen b * q + r = a und 0 <= r <b beibehält.

25
Kevin

Es gibt keine beste Möglichkeit, mit Ganzzahldivisionen und Modifikationen mit negativen Zahlen umzugehen. Es wäre schön, wenn a/b Die gleiche Größe und das entgegengesetzte Vorzeichen von (-a)/b Hätte. Es wäre schön, wenn a % b Tatsächlich ein Modulo wäre. B. Da wir wirklich a == (a/b)*b + a%b wollen, sind die ersten beiden nicht kompatibel.

Welche zu behalten ist, ist eine schwierige Frage, und es gibt Argumente für beide Seiten. C und C++ runden die Ganzzahldivision gegen Null ab (also a/b == -((-a)/b)), und anscheinend Python nicht.

8
David Thornley

Wie bereits erwähnt, macht Python modulo eine wohlüberlegte Ausnahme von den Konventionen anderer Sprachen.

Dies gibt negativen Zahlen ein nahtloses Verhalten, insbesondere wenn sie in Kombination mit dem Integer-Divide-Operator // verwendet werden, wie es % modulo häufig ist (wie in math . divmod =):

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

Produziert:

 -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
  • Python % gibt immer null oder positiv aus, wenn der Divisor positiv ist
  • Python // rundet immer gegen negative Unendlichkeit
4
Bob Stein

Modulo, Äquivalenzklassen für 4:

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

Hier ist ein Link zu Modulos Verhalten mit negativen Zahlen . (Ja, ich habe gegoogelt)

3
wheaties

Ich dachte auch, dass es ein seltsames Verhalten von Python war. Es stellt sich heraus, dass ich die Teilung nicht gut gelöst habe (auf Papier); Ich gab dem Quotienten einen Wert von 0 und dem Rest einen Wert von -5. Schrecklich ... Ich habe die geometrische Darstellung ganzer Zahlen vergessen. Durch Abrufen der durch die Zahlenlinie angegebenen Geometrie von Ganzzahlen können die korrekten Werte für den Quotienten und den Rest ermittelt und das Verhalten von Python überprüft werden. (Obwohl ich davon ausgehe, dass Sie Ihr Anliegen schon vor langer Zeit gelöst haben).

1
joser

Es ist auch erwähnenswert, dass sich auch die Unterteilung in python von C: Consider unterscheidet

>>> x = -10
>>> y = 37

in C erwarten Sie das Ergebnis

0

was ist X/Y in Python?

>>> print x/y
-1

und% ist modulo - nicht der Rest! Während x% y in C ergibt

-10

python-Ausbeuten.

>>> print x%y
27

Sie können beide wie in C erhalten

Der Unternehmensbereich:

>>> from math import trunc
>>> d = trunc(float(x)/y)
>>> print d
0

Und der Rest (mit der Einteilung von oben):

>>> r = x - d*y
>>> print r
-10

Diese Berechnung ist möglicherweise nicht die schnellste, funktioniert jedoch für alle Vorzeichenkombinationen von x und y, um die gleichen Ergebnisse wie in C zu erzielen, und vermeidet bedingte Anweisungen.

0
bebbo