Zuweisen einer Variablen NaN in Python ohne Numpy

103

Die meisten Sprachen haben eine NaN-Konstante, mit der Sie einer Variablen den Wert NaN zuweisen können. Kann Python dies ohne Verwendung von Numpy tun?

Zelinka
quelle
1
C, C ++, Java, C #, Ocaml, es ist Teil vieler Sprachen.
Zelinka
2
NaN in C ist NAN; Es ist eine Konstante math.h, die ab C99 in definiert ist. (Ich halte es für fair, die neueste standardisierte Version der Sprache als diese Sprache zu bezeichnen. Daher ist "C" C11.) (Siehe stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in -c ); In C ++ NANgibt es das auch nan(), nanf()und nanl()obwohl ich etwas weniger sicher bin, was sie tun. double.NaNin Java, Double.NaNin C #…
Thanatos

Antworten:

168

Ja - verwenden math.nan.

>>> from math import nan
>>> print(nan)
nan
>>> print(nan + 2)
nan
>>> nan == nan
False
>>> import math
>>> math.isnan(nan)
True

Vor Python 3.5 konnte man verwenden float("nan")(ohne Berücksichtigung der Groß- und Kleinschreibung).

Beachten Sie, dass die Überprüfung, ob zwei Dinge, die NaN sind, einander gleich sind, immer false zurückgibt. Dies liegt zum Teil daran, dass zwei Dinge, die "keine Zahl" sind, (genau genommen) nicht gleich sein können - siehe Was ist der Grund für alle Vergleiche, die für IEEE754-NaN-Werte falsch zurückgeben? Weitere Details und Informationen.

Verwenden math.isnan(...)Sie stattdessen, wenn Sie feststellen müssen, ob ein Wert NaN ist oder nicht.

Darüber hinaus kann die genaue Semantik der ==Operation für den NaN-Wert subtile Probleme verursachen, wenn versucht wird, NaN in Containertypen wie listoder zu speicherndict (oder bei Verwendung benutzerdefinierter Containertypen) . Weitere Informationen finden Sie unter Überprüfen des Vorhandenseins von NaN in einem Behälter .


Sie können NaN-Zahlen auch mit Pythons Dezimalzahl erstellen :

>>> from decimal import Decimal
>>> b = Decimal('nan')
>>> print(b)
NaN
>>> print(repr(b))
Decimal('NaN')
>>>
>>> Decimal(float('nan'))
Decimal('NaN')
>>> 
>>> import math
>>> math.isnan(b)
True

math.isnan(...) funktioniert auch mit Dezimalobjekten.


Sie können jedoch keine Python-Zahlen im Python- Fraktionsmodul erstellen:

>>> from fractions import Fraction
>>> Fraction('nan')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python35\lib\fractions.py", line 146, in __new__
    numerator)
ValueError: Invalid literal for Fraction: 'nan'
>>>
>>> Fraction(float('nan'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python35\lib\fractions.py", line 130, in __new__
    value = Fraction.from_float(numerator)
  File "C:\Python35\lib\fractions.py", line 214, in from_float
    raise ValueError("Cannot convert %r to %s." % (f, cls.__name__))
ValueError: Cannot convert nan to Fraction.

Im übrigen können Sie auch tun float('Inf'), Decimal('Inf')oder math.inf(3.5+) unendliche Zahlen zuzuordnen. (Und siehe auch math.isinf(...))

Jedoch zu tun Fraction('Inf')oder Fraction(float('inf'))nicht erlaubt und wird eine Ausnahme auslösen, genau wie NaN.

Wenn Sie schnell und einfach überprüfen möchten, ob eine Zahl weder NaN noch unendlich ist, können Sie sie verwenden math.isfinite(...) ab Python 3.2+ verwenden.


Wenn Sie ähnliche Prüfungen mit komplexen Zahlen durchführen möchten, cmathenthält das Modul einen ähnlichen Satz von Funktionen und Konstanten wie das mathModul:

Michael0x2a
quelle
2
Beachten Sie, dass die Verwendung von float ('nan) 3x langsamer ist als die Verwendung von np.nan und etwa 6,5-mal langsamer als die einmalige Zuweisung von nan = float (' nan ') und die anschließende Verwendung der Variablen' nan 'für alle folgenden Zuweisungen (wie in abarnert vorgeschlagen) Antworten).
Daniel Goldfarb
18
nan = float('nan')

Und jetzt hast du die Konstante , nan.

Sie können auf ähnliche Weise NaN-Werte für die Dezimalzahl erstellen.

dnan = Decimal('nan')
abarnert
quelle
Dies ist die effizienteste Antwort für mehrere Nan-Zuweisungen: Verwenden Sie float ('nan') nur einmal und verwenden Sie dann die zugewiesene Konstante für alle verbleibenden Zuweisungen. Wenn Sie jedoch nur ein oder zwei Zuweisungen von nan total ausführen, ist die Verwendung von numpy.nan am schnellsten.
Daniel Goldfarb
7

Verwendung float("nan"):

>>> float("nan")
nan
orlp
quelle
6

Sie können tun float('nan'), um NaN zu bekommen.

BrenBarn
quelle
6

Sie können NaN von "inf - inf" erhalten, und Sie können "inf" von einer Zahl größer als 2e308 erhalten. Daher habe ich im Allgemeinen Folgendes verwendet:

>>> inf = 9e999
>>> inf
inf
>>> inf - inf
nan
Junior Polegato
quelle
3
Diese Antwort wurde unangemessen abgelehnt. Ich schreibe viele kleine Parsing-Tests in TXT-Dateien und verwende ast.literal_eval, um den erwarteten Ausgabeteil zu erhalten. Es ist unmöglich, dort float ('nan') zu nennen, und diese Antwort war hilfreich für mich.
Vitalik Verhovodov
0

Eine konsistentere (und weniger undurchsichtige) Methode zum Generieren von inf und -inf ist die erneute Verwendung von float ():

>> positive_inf = float('inf')
>> positive_inf
inf
>> negative_inf = float('-inf')
>> negative_inf
-inf

Beachten Sie, dass die Größe eines Floats je nach Architektur unterschiedlich ist. Daher ist es wahrscheinlich am besten, magische Zahlen wie 9e999 zu vermeiden, auch wenn dies wahrscheinlich funktioniert.

import sys
sys.float_info
sys.float_info(max=1.7976931348623157e+308,
               max_exp=1024, max_10_exp=308,
               min=2.2250738585072014e-308, min_exp=-1021,
               min_10_exp=-307, dig=15, mant_dig=53,
               epsilon=2.220446049250313e-16, radix=2, rounds=1)
user3685621
quelle