Zuerst dachte ich, dies sei nur eine weitere Frage, die in einem Interview gestellt werden könnte. Wenn Sie Ihr Gehirn richtig einsetzen, können Sie wahrscheinlich erraten, wie das Ergebnis aussehen wird. Er lehnte sich in seinem Stuhl zurück und begann zu denken, die Logik einzuschalten und sich an etwas zu erinnern, auf das er sich beim Denken verlassen konnte. Aber vergeblich! Plötzlich wurde klar, dass die Antwort nicht gefunden werden konnte. Aber warum? Was müssen Sie verstehen, um es zu finden? In Mathematik? In einer Programmiersprache?
Die Antwort sollte NaN sein. Aber warum bin ich mir da nicht sicher? Ich war zuversichtlich, dass alle Ausdrücke, die NaN enthalten, NaN zurückgeben würden. Nun, vielleicht nur, wenn Sie NaN durch Null teilen - in diesem Fall wird eine ZeroDivisionError- Ausnahme ausgelöst . Einhundert Prozent NaN!
Ich gebe den Ausdruck in eine Notizblockzelle ein:
>>> 1**nan + 1**nan
2.0
Tatsächlich? Warten:
>>> arange(5)**nan
array([nan, 1., nan, nan, nan])
Das heißt, aus irgendeinem Grund ist eins zur NaN-Potenz eins, aber Null und alle anderen Zahlen zur NaN-Potenz sind NaN. Wo ist die Logik? Was ist los?
Also lass uns noch einmal gehen:
>>> 0**nan, 1**nan
(nan, 1.0)
Vielleicht war ich nur wegen des Mangels an praktischem Bedarf an tiefem Wissen über NaN, ich habe einfach nichts vermutet? Oder vielleicht wusste ich es, aber vergessen? Oder vielleicht noch schlimmer - ich wusste es nicht und vergaß es?
Wir gehen zu Wikipedia . Dort wird dieses Problem auch als Problem bezeichnet, aber warum alles so angeordnet ist, wird in keiner Weise erklärt. Aber das habe ich gelernt:
>>> hypot(inf, nan)
inf
Obwohl zur gleichen Zeit:
>>> sqrt(inf**2 + nan**2)
nan
Das ist auch ein bisschen seltsam.
Okay, von Wikipedia gehen wir zu C99 auf Seite 182 und erhalten schließlich eine logische Erklärung, warum pow (x, 0) für jedes x 1 zurückgibt , auch für x gleich NaN:
>>> power(nan, 0)
1.0
Wenn die Funktion wird zur Macht erhoben und worin tendiert zu 0, dann ist das Ergebnis 1, unabhängig davon, welcher Wert ist ...
Und wenn das Ergebnis nicht vom numerischen Wert der Funktion abhängt, dann ist 1 ein gültiges Ergebnis, auch für NaN. Dies erklärt jedoch immer noch nicht, warum 1 zur NaN-Potenz 1 ist. Wir
suchen nach einem anderen C99 und auf Seite 461 sehen wir keine Erklärung, nur die Anforderung, dass pow (+1, y) 1 für alle y zurückgeben sollte , sogar gleich NaN. Alles.
Andererseits legt die Erklärung, warum pow (NaN, 0) = 1 gegenüber pow (NaN, 0) = NaN vorzuziehen ist, immer noch nahe, dass NaN nicht wörtlich als Nicht-Zahl verstanden werden sollte ... Angenommen, wir haben aufgrund einiger Berechnungen eine Zahl erhalten, die die für diesen Zahlentyp zugewiesene Speichergröße überschreitet, zum Beispiel:
>>> a = pi*10e307
>>> a
inf
Als Ergebnis haben wir inf bekommen , was genau diese Nummer wir nicht kennen, aber es ist trotzdem eine Art Nummer. Dann haben wir immer wieder etwas berechnet und eine zu große Zahl bekommen:
>>> b = e*10e307
>>> b
inf
Der Unterschied zwischen a und b gibt NaN zurück:
>>> c = a - b
>>> c
nan
Der einzige Grund, warum wir uns c als keine Zahl vorstellen können, ist, dass wir keine genauen Berechnungen verwendet haben. In c ist unter NaN jedoch eine Bedeutung verborgen. Wir wissen nicht, was diese Bedeutung ist. Aber es ist immer noch eine Zahl, und da dies eine Zahl ist, ist es nicht überraschend, dass pow (1, NaN) = 1 ist .
Warum dann pow (0, NaN) = NaN ? Tatsache ist, dass wir wirklich Null bekommen, wenn wir 0 auf eine Potenz erhöhen. Mit Ausnahme eines Einzelfalls - wenn der Abschluss 0 ist:
>>> 0**0
1
Aus diesem Grund gibt es im Ausdruck pow (0, NaN) eine Mehrdeutigkeit mit einem bestimmten Wert von NaN. Natürlich ist die Wahrscheinlichkeit, dass 0 unter NaN versteckt werden kann, verschwindend gering, und man könnte annehmen, dass pow (0, NaN) = 0 ist . Aber es ist immer noch besser, auf Nummer sicher zu gehen. Man weiß nie, wozu das führen kann. Vielleicht haben sie so argumentiert, als die Standards erstellt wurden.
Ich weiß nicht einmal, was ich sonst noch sagen soll ... Wenn Sie die Antwort im Voraus wussten, können Sie höchstwahrscheinlich beneidet werden, da die Bereiche, in denen dieses Wissen nützlich sein kann, wahrscheinlich voller interessanter Aufgaben sind. Und vielleicht auch umgekehrt. Schreiben Sie darüber in den Kommentaren.
PS Da sich NaN auf Gleitkommazahlen bezieht, kann es sich um einen Wörterbuchschlüssel handeln:
>>> d = {0.1: 'a', nan: 'b'}
>>> d[nan]
'b'
Ist es sinnvoll, dies in der Praxis anzuwenden? Ich denke nicht, dass es besser ist.