Przypisywanie zmiennej NaN w Pythonie bez numpy

Większość języków ma stałą NaN, której można użyć do przypisania zmiennej wartości NaN. Czy python może to zrobić bez użycia numpy?

Author: zelinka, 2013-10-15

6 answers

Tak -- użyj float('nan'). Począwszy od Pythona 3.5, można również użyć math.nan.

>>> a = float('nan')
>>> print(a)
nan
>>> print(a + 2)
nan
>>> a == a
False
>>> import math
>>> math.isnan(a)
True
>>> # Python 3.5+
>>> math.isnan(math.nan)
True

Funkcja float(...) jest niewrażliwa na wielkość liter -- Robienie float('NAN') lub float('naN') lub podobnych rzeczy również będzie działać.

Zauważ, że sprawdzanie, czy dwie rzeczy, które są NaN są sobie równe, zawsze zwróci false. Dzieje się tak po części dlatego, że dwie rzeczy, które nie są liczbą, nie mogą (ściśle mówiąc) być równe sobie -- zobacz Jakie jest uzasadnienie dla wszystkich porównań zwracanie false Dla wartości NaN IEEE754? Po Więcej szczegółów i informacji.

Zamiast tego użyj math.isnan(...) jeśli chcesz określić, czy wartość jest NaN, czy nie.

Ponadto, dokładna semantyka operacji == na wartości NaN może powodować subtelne problemy podczas próby przechowywania NaN wewnątrz typów kontenerów, takich jak list lub dict (lub podczas używania niestandardowych typów kontenerów). Zobacz sprawdzanie obecności NaN w pojemniku Po Więcej Szczegółów.


Możesz również konstruuj liczby NaN używając modułu dziesiętnego Pythona:

>>> 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(...) będzie również działać z obiektami dziesiętnymi.


Jednak nie możnakonstruować liczb NaN w module ułamków:

>>> 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.

Nawiasem mówiąc, można również zrobić float('Inf'), Decimal('Inf'), lub math.inf (3.5+) aby przypisać nieskończone liczby. (Zobacz też math.isinf(...))

Jednak Robienie Fraction('Inf') lub Fraction(float('inf')) nie jest dozwolone i rzuci wyjątek, tak jak NaN.

Jeśli chcesz szybko i łatwo sprawdzić, czy liczba nie jest ani NaN, ani nieskończona, możesz użyć math.isfinite(...) od Pythona 3.2+.


Jeśli chcesz wykonać podobne kontrole z liczbami zespolonymi, moduł cmath zawiera podobny zestaw funkcji i stałych jak moduł math:

 108
Author: Michael0x2a,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-09 04:05:13
nan = float('nan')

I teraz masz stałą, nan.

Można podobnie tworzyć wartości NaN dla dziesiętnych.Dziesiętne.:

dnan = Decimal('nan')
 11
Author: abarnert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-15 06:05:56

Użycie float("nan"):

>>> float("nan")
nan
 6
Author: orlp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-15 06:05:20

Możesz zrobić float('nan'), aby dostać NaN.

 5
Author: BrenBarn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-15 06:05:34

Możesz uzyskać NaN z "inf-inf", a " inf " z liczby większej niż 2e308, więc ogólnie używałem:

>>> inf = 9e999
>>> inf
inf
>>> inf - inf
nan
 1
Author: Junior Polegato,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-04 21:20:30

Bardziej spójnym (i mniej nieprzezroczystym) sposobem generowania inf i-inf jest ponowne użycie float ():

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

Zauważ, że rozmiar float ' a różni się w zależności od architektury, więc prawdopodobnie najlepiej jest unikać używania magicznych liczb, takich jak 9e999, nawet jeśli to może zadziałać.

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)
 0
Author: user3685621,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-21 22:02:08