Призначення змінної NaN в python без numpy


103

Більшість мов мають постійну NaN, яку можна використовувати для призначення змінної значення NaN. Чи може пітон це зробити, не використовуючи numpy?


1
C, C ++, java, C #, ocaml, її частина багатьох мов.
zelinka

2
NaN, в С, є NAN; це константа, визначена в math.hC99. (Я вважаю, що найновішою стандартизованою версією мови справедливо називати цю мову. Таким чином, "C" - це C11.) (Див. Stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in -с ); в C ++, це NANтак само, є також nan(), nanf()і nanl(), хоча я трохи менш впевнений щодо того , що вони роблять. double.NaNна Яві, Double.NaNв C #…
Танатос

Відповіді:


169

Так - використовувати math.nan.

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

До Python 3.5 можна було скористатися float("nan")(нечутливим до регістру).

Зауважте, що перевірка того, чи дві речі, які є NaN, рівні одна одній, завжди повертатиметься помилково. Це частково тому, що дві речі, які "не є числом", не можна (суворо кажучи) сказати, рівними одна одній - див. Яке обґрунтування для всіх порівнянь, що повертають помилкові значення NaN IEEE754? для отримання детальної інформації та інформації.

Натомість використовуйте, math.isnan(...)якщо вам потрібно визначити, є значення NaN чи ні.

Крім того, точна Семантика ==операції на значенні NaN може викликати тонкі проблеми при спробі зберегти NaN всередині типів контейнерів , такі як listабо dict(або при використанні призначених для користувача типів контейнерів). Детальнішу інформацію див. У розділі Перевірка наявності NaN у контейнері .


Ви також можете побудувати числа NaN за допомогою десяткового модуля Python :

>>> 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(...) також буде працювати з об’єктами Decimal.


Однак ви не можете побудувати числа NaN в модулі дробів Python :

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

Між іншим, ви також можете зробити float('Inf'), Decimal('Inf')або math.inf(3.5+) призначити нескінченні числа. (А також дивіться math.isinf(...))

Однак робити Fraction('Inf')або Fraction(float('inf'))забороняється, і буде виняток, як і NaN.

Якщо ви хочете, щоб швидкий і простий спосіб перевірити, чи число не є ні NaN, ні нескінченним, ви можете використовувати math.isfinite(...)з Python 3.2+.


Якщо ви хочете зробити подібні перевірки зі складними числами, cmathмодуль містить аналогічний набір функцій і констант, як і mathмодуль:


2
Зверніть увагу, що використання float ('nan) в 3 рази повільніше, ніж використання np.nan, і приблизно в 6,5 рази повільніше, ніж призначення один раз nan = float (' nan '), а потім використання змінної' nan 'для всіх наступних призначень (як це запропоновано в abarnert's відповідь).
Даніель Голдфарб

18
nan = float('nan')

І тепер у вас є постійна, nan.

Можна аналогічно створити значення NaN для десяткових знаків.

dnan = Decimal('nan')

Це найефективніша відповідь для декількох нан-призначень: тобто використовуйте float ('nan') лише один раз, а потім використовуйте призначену константу для всіх інших завдань. Однак якщо ви виконуєте лише одне або два завдання загальної кількості нан, то використання numpy.nan найшвидше.
Даніель Голдфарб



6

Ви можете отримати NaN від "inf - inf", а ви можете отримати "inf" з числа, що перевищує 2e308, тому я зазвичай використовував:

>>> inf = 9e999
>>> inf
inf
>>> inf - inf
nan

3
Цю відповідь необґрунтовано заперечували. Я пишу багато невеликих тестів для розбору у файлах .txt та використовую ast.literal_eval, щоб отримати очікувану вихідну частину. Там не можна назвати float ('nan'), і ця відповідь була для мене корисною.
Віталік Верховодов

0

Більш послідовний (і менш непрозорий) спосіб генерування inf та -inf - це знову використовувати float ():

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

Зауважте, що розмір поплавця змінюється в залежності від архітектури, тому, ймовірно, найкраще уникати використання магічних чисел, таких як 9e999, навіть якщо це, ймовірно, спрацює.

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.