Ich habe in Python ein seltsames Verhalten in Bezug auf negative Zahlen festgestellt:
>>> -5 % 4
3
Könnte jemand erklären, was los ist?
Ich habe in Python ein seltsames Verhalten in Bezug auf negative Zahlen festgestellt:
>>> -5 % 4
3
Könnte jemand erklären, was los ist?
..., -9, -5, -1, 3, 7, ...
math.fmod
das gleiche Verhalten wie in C oder Java verwenden.
Antworten:
Im Gegensatz zu C oder C ++ gibt Pythons Modulo-Operator ( %
) immer eine Zahl mit dem gleichen Vorzeichen wie der Nenner (Divisor) zurück. Ihr Ausdruck ergibt 3, weil
(-5) / 4 = -1,25 -> Boden (-1,25) = -2
(-5)% 4 = (-2 × 4 + 3)% 4 = 3.
Es wird dem C-Verhalten vorgezogen, da ein nicht negatives Ergebnis oft nützlicher ist. Ein Beispiel ist die Berechnung von Wochentagen. Wenn heute Dienstag (Tag 2) ist, was ist der Wochentag N Tage zuvor? In Python können wir mit berechnen
return (2 - N) % 7
aber in C, wenn N ≥ 3 ist, erhalten wir eine negative Zahl, die eine ungültige Zahl ist, und wir müssen sie manuell korrigieren, indem wir 7 hinzufügen:
int result = (2 - N) % 7;
return result < 0 ? result + 7 : result;
(Unter http://en.wikipedia.org/wiki/Modulo_operator erfahren Sie, wie das Vorzeichen des Ergebnisses für verschiedene Sprachen bestimmt wird.)
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.
a
, positiv b
, während Python-Stockwerke. Es ist immer wahr abs(r) < b
, und sie decken iff r <= 0
.
Es gibt keinen besten Weg, um mit Ganzzahldivision und Mods mit negativen Zahlen umzugehen. Es wäre schön, wenn a/b
es die gleiche Größe und das entgegengesetzte Vorzeichen von wäre (-a)/b
. Es wäre schön, wenn a % b
es tatsächlich ein Modulo b wäre. Da wir wirklich wollen a == (a/b)*b + a%b
, 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 (so a/b == -((-a)/b)
), und Python anscheinend nicht.
Wie bereits erwähnt, macht Python modulo eine gut begründete 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
%
gibt immer Null oder Positiv aus, wenn der Divisor positiv ist//
rundet immer in Richtung negative UnendlichkeitIn Python funktioniert der Modulo-Operator folgendermaßen.
>>> mod = n - math.floor(n/base) * base
Das Ergebnis ist also (für Ihren Fall):
mod = -5 - floor(-1.25) * 4
mod = -5 - (-2*4)
mod = 3
Während andere Sprachen wie C, JAVA und JavaScript die Kürzung anstelle von Floor verwenden.
>>> mod = n - int(n/base) * base
was in ... endet:
mod = -5 - int(-1.25) * 4
mod = -5 - (-1*4)
mod = -1
Wenn Sie weitere Informationen zum Runden in Python benötigen, lesen Sie diese .
Modulo, Äquivalenzklassen für 4:
Hier ist ein Link zu Modulos Verhalten mit negativen Zahlen . (Ja, ich habe gegoogelt)
Ich dachte auch, dass es ein seltsames Verhalten von Python war. Es stellt sich heraus, dass ich die Trennung nicht gut gelöst habe (auf dem Papier); Ich gab dem Quotienten einen Wert von 0 und dem Rest einen Wert von -5. Schrecklich ... Ich habe die geometrische Darstellung von Ganzzahlen vergessen. Durch Abrufen der Geometrie der Ganzzahlen, die durch die Zahlenlinie angegeben werden, können die korrekten Werte für den Quotienten und den Rest ermittelt und überprüft werden, ob das Verhalten von Python in Ordnung ist. (Obwohl ich davon ausgehe, dass Sie Ihr Problem bereits vor langer Zeit gelöst haben).
Erwähnenswert ist auch, 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 ergibt.
>>> 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 (unter Verwendung der Unterteilung 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. Außerdem werden bedingte Anweisungen vermieden.