Beachten Sie, dass die Konstante 1e309als interpretiert wird +infund -1e309als interpretiert wird -inf.
Chris Taylor
Antworten:
97
Sie können immer noch NaN-Werte (Not-a-Number) durch einfache Arithmetik erhalten, die Folgendes umfasst inf:
>>>0* float("inf")
nan
Beachten Sie, dass Sie in der Regel nicht eine bekommen infWert durch übliche arithmetische Berechnungen:
>>>2.0**24.0>>> _**216.0>>> _**2256.0>>> _**265536.0>>> _**24294967296.0>>> _**21.8446744073709552e+19>>> _**23.4028236692093846e+38>>> _**21.157920892373162e+77>>> _**21.3407807929942597e+154>>> _**2Traceback(most recent call last):File"<stdin>", line 1,in?OverflowError:(34,'Numerical result out of range')
Der infWert wird als ein ganz besonderer Wert mit ungewöhnlicher Semantik betrachtet. Es ist daher besser, OverflowErrorsofort über eine Ausnahme Bescheid zu wissen , als einen infWert stillschweigend in Ihre Berechnungen einfließen zu lassen.
Eine einfache Float-Addition, Multiplikation usw. erzeugt jedoch glücklich inf: f = 1.3407807929942597e + 154; f * f => inf. Es scheint eher eine Ausnahme von ** zu sein, einen OverflowError auszulösen.
Eregon
@eregon **scheint eigentlich ein bisschen fehlerhaft . Wenn es mit reellen Zahlen überläuft, gibt es einen Fehler aus, aber wenn einer seiner Operanden infoder ist -inf, gibt es entweder 0.0oder zurück inf. Es funktioniert also korrekt, wenn die Eingabe unendlich ist, aber nicht, wenn das Ergebnis unendlich sein sollte.
Abel
2
@Abel Das ist kein Buggy. Überlaufen bedeutet, dass die Anzahl sehr groß ist. Zu groß, um es darzustellen, aber immer noch viel kleiner als unendlich. Das Platzieren von unendlich an einem solchen Ort kann für den Ausnahmebehandler Ihrer speziellen Anwendungslogik nützlich sein, wäre jedoch für Python im Allgemeinen falsch.
Lutz Prechelt
6
@Lutz Wenn es dann als Multiplikation auftaucht, ist es immer noch inkonsistentes Verhalten. Sicherlich ist groß * groß auch nicht unendlich.
Die folgenden Abschnitte gelten gleichermaßen für jede Sprache, die IEEE-Gleitkomma-Arithmetik korrekt implementiert. Sie ist nicht nur für Python spezifisch.
Vergleich für Ungleichheit
Beim Umgang mit unendlich und Operatoren, die größer >oder kleiner als <sind, zählt Folgendes:
Jede Zahl einschließlich +infist höher als-inf
Jede Zahl einschließlich -infist niedriger als+inf
Jeder Vergleich NaNist falsch ( infweder höher noch niedriger als NaN)
Vergleich für Gleichheit
Im Vergleich zur Gleichheit +infund +infsind gleich, wie -infund -inf. Dies ist ein viel diskutiertes Thema und mag für Sie kontrovers klingen, aber es ist im IEEE-Standard und Python verhält sich einfach so.
Natürlich +infist ungleich -infund alles, einschließlich sich NaNselbst, ist ungleich NaN.
Berechnungen mit unendlich
Die meisten Berechnungen mit unendlich ergeben unendlich, es sei denn, beide Operanden sind unendlich, wenn die Operation Division oder Modulo oder bei Multiplikation mit Null einige spezielle Regeln zu beachten sind:
Wenn es mit Null multipliziert wird, für das das Ergebnis undefiniert ist, ergibt es NaN
wenn eine beliebige Zahl (außer unendlich selbst) durch unendlich geteilt wird, was ergibt 0.0oder -0.0².
Wenn die positive oder negative Unendlichkeit durch positive oder negative Unendlichkeit geteilt wird (einschließlich Modulo), ist das Ergebnis undefiniert NaN.
Beim Subtrahieren mögen die Ergebnisse überraschend sein, folgen aber dem gesunden Menschenverstand :
dabei inf - infist das Ergebnis undefiniert : NaN;
wenn Sie dies tun inf - -inf, ist das Ergebnis inf;
wenn Sie dies tun -inf - inf, ist das Ergebnis -inf;
Dabei -inf - -infist das Ergebnis undefiniert : NaN.
Beim Hinzufügen kann es auch ähnlich überraschend sein:
wenn Sie dies tun inf + inf, ist das Ergebnis inf;
dabei inf + -infist das Ergebnis undefiniert : NaN;
dabei -inf + infist das Ergebnis undefiniert : NaN;
Wenn Sie dies tun -inf + -inf, ist das Ergebnis -inf.
mit math.pow, powoder **ist schwierig, da es nicht benimmt , wie es sollte. Es wird eine Überlaufausnahme ausgelöst, wenn das Ergebnis mit zwei reellen Zahlen zu hoch ist, um auf einen Float mit doppelter Genauigkeit zu passen (es sollte unendlich zurückgeben), aber wenn die Eingabe infoder ist -inf, verhält es sich korrekt und gibt entweder infoder zurück 0.0. Wenn das zweite Argument ist NaN, wird es zurückgegeben NaN, es sei denn, das erste Argument ist 1.0. Es gibt weitere Probleme, die nicht alle in den Dokumenten behandelt werden .
math.expleidet die gleichen Probleme wie math.pow. Eine Lösung, um dies für einen Überlauf zu beheben, besteht darin, ähnlichen Code zu verwenden:
try:
res = math.exp(420000)exceptOverflowError:
res = float('inf')
Anmerkungen
Anmerkung 1: Als zusätzliche Einschränkung, die gemäß IEEE-Standard definiert ist, ist das Ergebnis, wenn Ihr Berechnungsergebnis unter- oder überläuft, kein Unter- oder Überlauffehler, sondern eine positive oder negative Unendlichkeit: 1e308 * 10.0Ausbeute inf.
Hinweis 2: Da jede Berechnung mit NaNRückgaben NaNund jeder Vergleich mit NaN, einschließlich sich NaNselbst, erfolgt false, sollten Sie die math.isnanFunktion verwenden, um festzustellen, ob eine Zahl tatsächlich ist NaN.
Hinweis 3: Obwohl Python das Schreiben unterstützt float('-NaN'), wird das Zeichen ignoriert, da NaNintern kein Anmelden vorhanden ist . Wenn Sie teilen -inf / +inf, ist das Ergebnis NaNnicht -NaN(so etwas gibt es nicht).
Hinweis 4: Achten Sie darauf, dass Sie sich auf die oben genannten Punkte verlassen, da Python auf der C- oder Java-Bibliothek basiert, für die es kompiliert wurde, und nicht alle zugrunde liegenden Systeme dieses Verhalten korrekt implementieren. Wenn Sie sicher sein möchten, testen Sie vor den Berechnungen auf Unendlich.
¹) In letzter Zeit bedeutet seit Version 3.2 .
²) Gleitkommazahlen unterstützen positive und negative Nullen, also: x / float('inf')behält Vorzeichen und -1 / float('inf')Renditen -0.0, 1 / float(-inf)Renditen -0.0, 1 / float('inf')Renditen 0.0und -1/ float(-inf)Renditen 0.0. Darüber hinaus 0.0 == -0.0isttrue , müssen Sie manuell die Zeichen , wenn Sie es wahr sein nicht wollen.
Ein kleiner Trottel: Nicht jede Berechnung mit unendlich ergibt unendlich:-1 * float('infinity') == -inf
Evan Krall
4
Deshalb habe ich gesagt, es sei ein kleiner Trottel. Sie hatten mir eine Minute lang Sorgen gemacht, dass das Zeichen bei der Arbeit mit der Unendlichkeit völlig ignoriert würde, und ich wollte es anderen Menschen klarstellen.
Evan Krall
12
Na ja, fast: 1 / float ('unendlich') == 0.0
Phil
3
@Phil: Obwohl ich mir ziemlich sicher bin, dass Sie nur versucht haben zu zeigen, dass nicht alle Berechnungen mit inf zu inf oder NaN führen, wollte ich nur anderen klar machen, die möglicherweise die Kommentare lesen, dass 1 / float ('unendlich) ') == 0.0 ist wahr; Wenn Sie sich der Unendlichkeit nähern, nähert sich das Ergebnis der Division 0. Ich weiß, es ist nur eine Grundrechnung, aber ich wollte sichergehen, dass die Leser verstehen oder zumindest eine Ahnung haben, warum das Ergebnis das ist, was es ist.
Anthony Pace
1
Ich habe das Gefühl, dass diese Antwort viel besser ist als die akzeptierte Antwort.
Die von allen modernen Prozessoren verwendete IEEE 754-Gleitkommadarstellung weist mehrere spezielle Bitmuster auf, die für positive Unendlichkeit (Vorzeichen = 0, exp = ~ 0, frac = 0), negative Unendlichkeit (Vorzeichen = 1, exp = ~ 0, frac = 0) reserviert sind ) und viele NaN (keine Zahl: exp = ~ 0, frac ≠ 0).
Alles, worüber Sie sich Sorgen machen müssen: Einige Arithmetiken können Gleitkomma-Ausnahmen / Traps verursachen, aber diese sind nicht nur auf diese "interessanten" Konstanten beschränkt.
Wenn meine Arithmetik also zu groß ist, könnte sie zu einer Inf werden?
Casebash
@Casebash Nein, es wird eine verursachen OverflowError.
wizzwizz4
2
Ich habe eine Einschränkung gefunden, die bisher niemand erwähnt hat. Ich weiß nicht, ob es in praktischen Situationen häufig vorkommt, aber hier ist es der Vollständigkeit halber.
Normalerweise gibt sich die Berechnung einer Zahl Modulo Infinity als Float zurück, aber ein Bruchteil Modulo Infinity gibt zurück nan(keine Zahl). Hier ist ein Beispiel:
>>>from fractions importFraction>>>from math import inf
>>>3% inf
3.0>>>3.5% inf
3.5>>>Fraction('1/3')% inf
nan
1e309
als interpretiert wird+inf
und-1e309
als interpretiert wird-inf
.Antworten:
Sie können immer noch NaN-Werte (Not-a-Number) durch einfache Arithmetik erhalten, die Folgendes umfasst
inf
:Beachten Sie, dass Sie in der Regel nicht eine bekommen
inf
Wert durch übliche arithmetische Berechnungen:Der
inf
Wert wird als ein ganz besonderer Wert mit ungewöhnlicher Semantik betrachtet. Es ist daher besser,OverflowError
sofort über eine Ausnahme Bescheid zu wissen , als eineninf
Wert stillschweigend in Ihre Berechnungen einfließen zu lassen.quelle
**
scheint eigentlich ein bisschen fehlerhaft . Wenn es mit reellen Zahlen überläuft, gibt es einen Fehler aus, aber wenn einer seiner Operandeninf
oder ist-inf
, gibt es entweder0.0
oder zurückinf
. Es funktioniert also korrekt, wenn die Eingabe unendlich ist, aber nicht, wenn das Ergebnis unendlich sein sollte.Die Implementierung von Python folgt ziemlich gut dem IEEE-754-Standard , den Sie als Richtlinie verwenden können, basiert jedoch auf dem zugrunde liegenden System, auf dem es kompiliert wurde, sodass Plattformunterschiede auftreten können. Kürzlich¹ wurde ein Fix angewendet, der sowohl "unendlich" als auch "inf" zulässt , aber das ist hier von untergeordneter Bedeutung.
Die folgenden Abschnitte gelten gleichermaßen für jede Sprache, die IEEE-Gleitkomma-Arithmetik korrekt implementiert. Sie ist nicht nur für Python spezifisch.
Vergleich für Ungleichheit
Beim Umgang mit unendlich und Operatoren, die größer
>
oder kleiner als<
sind, zählt Folgendes:+inf
ist höher als-inf
-inf
ist niedriger als+inf
+inf
ist weder höher noch niedriger als+inf
-inf
ist weder höher noch niedriger als-inf
NaN
ist falsch (inf
weder höher noch niedriger alsNaN
)Vergleich für Gleichheit
Im Vergleich zur Gleichheit
+inf
und+inf
sind gleich, wie-inf
und-inf
. Dies ist ein viel diskutiertes Thema und mag für Sie kontrovers klingen, aber es ist im IEEE-Standard und Python verhält sich einfach so.Natürlich
+inf
ist ungleich-inf
und alles, einschließlich sichNaN
selbst, ist ungleichNaN
.Berechnungen mit unendlich
Die meisten Berechnungen mit unendlich ergeben unendlich, es sei denn, beide Operanden sind unendlich, wenn die Operation Division oder Modulo oder bei Multiplikation mit Null einige spezielle Regeln zu beachten sind:
NaN
0.0
oder-0.0
².NaN
.inf - inf
ist das Ergebnis undefiniert :NaN
;inf - -inf
, ist das Ergebnisinf
;-inf - inf
, ist das Ergebnis-inf
;-inf - -inf
ist das Ergebnis undefiniert :NaN
.inf + inf
, ist das Ergebnisinf
;inf + -inf
ist das Ergebnis undefiniert :NaN
;-inf + inf
ist das Ergebnis undefiniert :NaN
;-inf + -inf
, ist das Ergebnis-inf
.math.pow
,pow
oder**
ist schwierig, da es nicht benimmt , wie es sollte. Es wird eine Überlaufausnahme ausgelöst, wenn das Ergebnis mit zwei reellen Zahlen zu hoch ist, um auf einen Float mit doppelter Genauigkeit zu passen (es sollte unendlich zurückgeben), aber wenn die Eingabeinf
oder ist-inf
, verhält es sich korrekt und gibt entwederinf
oder zurück0.0
. Wenn das zweite Argument istNaN
, wird es zurückgegebenNaN
, es sei denn, das erste Argument ist1.0
. Es gibt weitere Probleme, die nicht alle in den Dokumenten behandelt werden .math.exp
leidet die gleichen Probleme wiemath.pow
. Eine Lösung, um dies für einen Überlauf zu beheben, besteht darin, ähnlichen Code zu verwenden:Anmerkungen
Anmerkung 1: Als zusätzliche Einschränkung, die gemäß IEEE-Standard definiert ist, ist das Ergebnis, wenn Ihr Berechnungsergebnis unter- oder überläuft, kein Unter- oder Überlauffehler, sondern eine positive oder negative Unendlichkeit:
1e308 * 10.0
Ausbeuteinf
.Hinweis 2: Da jede Berechnung mit
NaN
RückgabenNaN
und jeder Vergleich mitNaN
, einschließlich sichNaN
selbst, erfolgtfalse
, sollten Sie diemath.isnan
Funktion verwenden, um festzustellen, ob eine Zahl tatsächlich istNaN
.Hinweis 3: Obwohl Python das Schreiben unterstützt
float('-NaN')
, wird das Zeichen ignoriert, daNaN
intern kein Anmelden vorhanden ist . Wenn Sie teilen-inf / +inf
, ist das ErgebnisNaN
nicht-NaN
(so etwas gibt es nicht).Hinweis 4: Achten Sie darauf, dass Sie sich auf die oben genannten Punkte verlassen, da Python auf der C- oder Java-Bibliothek basiert, für die es kompiliert wurde, und nicht alle zugrunde liegenden Systeme dieses Verhalten korrekt implementieren. Wenn Sie sicher sein möchten, testen Sie vor den Berechnungen auf Unendlich.
¹) In letzter Zeit bedeutet seit Version 3.2 .
²) Gleitkommazahlen unterstützen positive und negative Nullen, also:
x / float('inf')
behält Vorzeichen und-1 / float('inf')
Renditen-0.0
,1 / float(-inf)
Renditen-0.0
,1 / float('inf')
Renditen0.0
und-1/ float(-inf)
Renditen0.0
. Darüber hinaus0.0 == -0.0
isttrue
, müssen Sie manuell die Zeichen , wenn Sie es wahr sein nicht wollen.quelle
-1 * float('infinity') == -inf
Das Gleiche gilt für C99 .
Die von allen modernen Prozessoren verwendete IEEE 754-Gleitkommadarstellung weist mehrere spezielle Bitmuster auf, die für positive Unendlichkeit (Vorzeichen = 0, exp = ~ 0, frac = 0), negative Unendlichkeit (Vorzeichen = 1, exp = ~ 0, frac = 0) reserviert sind ) und viele NaN (keine Zahl: exp = ~ 0, frac ≠ 0).
Alles, worüber Sie sich Sorgen machen müssen: Einige Arithmetiken können Gleitkomma-Ausnahmen / Traps verursachen, aber diese sind nicht nur auf diese "interessanten" Konstanten beschränkt.
quelle
OverflowError
.Ich habe eine Einschränkung gefunden, die bisher niemand erwähnt hat. Ich weiß nicht, ob es in praktischen Situationen häufig vorkommt, aber hier ist es der Vollständigkeit halber.
Normalerweise gibt sich die Berechnung einer Zahl Modulo Infinity als Float zurück, aber ein Bruchteil Modulo Infinity gibt zurück
nan
(keine Zahl). Hier ist ein Beispiel:Ich habe ein Problem mit dem Python-Bug-Tracker gemeldet. Es kann unter https://bugs.python.org/issue32968 eingesehen werden .
Update: Dies wird in Python 3.8 behoben .
quelle
in einem
1/x
Bruchteil istx = 1e-323
esinf
aber wannx = 1e-324
oder wenig es wirftZeroDivisionError
also sei vorsichtig!
quelle