Назначение переменной NaN в Python без numpy

103

В большинстве языков есть константа NaN, которую можно использовать для присвоения переменной значения NaN. Может ли Python сделать это без использования numpy?

зелинка
источник
1
C, C ++, java, C #, ocaml, это часть многих языков.
zelinka
2
NaN в C - это NAN; это константа, определенная в math.hC99. (Я считаю, что этим языком справедливо называть самую последнюю стандартизированную версию языка. Таким образом, «C» - это C11.) (См. Stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in -c ); в C ++ это NANтоже nan(), nanf()и nanl(), хотя я немного менее уверен в том, что они делают. double.NaNна Java, Double.NaNна C #…
Thanatos

Ответы:

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, всегда возвращает false. Отчасти это связано с тем, что две вещи, которые «не являются числами», нельзя (строго говоря) назвать равными друг другу - см. Каково обоснование всех сравнений, возвращающих false для значений 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модуль:

Майкл0x2a
источник
2
Обратите внимание, что использование float ('nan) в 3 раза медленнее, чем использование np.nan, и примерно в 6,5 раз медленнее, чем назначение nan = float (' nan ') один раз, а затем использование переменной' nan 'для всех последующих назначений (как предлагается в abarnert's ответ).
Даниэль Гольдфарб,
18
nan = float('nan')

И теперь у вас есть константа nan.

Аналогичным образом можно создать значения NaN для decimal.Decimal .:

dnan = Decimal('nan')
Abarnert
источник
Это наиболее эффективный ответ для нескольких назначений nan: то есть используйте float ('nan') только один раз, а затем используйте назначенную константу для всех остальных назначений. Однако, если вы выполняете только одно или два назначения всего nan, то использование numpy.nan будет самым быстрым.
Даниэль Гольдфарб,
7

Использование float("nan"):

>>> float("nan")
nan
orlp
источник
6

Можно сделать, float('nan')чтобы получить NaN.

BrenBarn
источник
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)
user3685621
источник