Asignar una variable NaN en Python sin numpy

103

La mayoría de los idiomas tienen una constante NaN que puede usar para asignar a una variable el valor NaN. ¿Puede Python hacer esto sin usar numpy?

zelinka
fuente
1
C, C ++, java, C #, ocaml, es parte de muchos lenguajes.
zelinka
2
NaN, en C, es NAN; es una constante definida en math.h, a partir de C99. (Creo que es justo llamar a la versión estandarizada más reciente del idioma como ese idioma. Por lo tanto, "C" es C11.) (Consulte stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in -c ); en C ++, es NANasí, también hay nan(), nanf()y nanl(), aunque estoy un poco menos seguro en cuanto a lo que hacen. double.NaNen Java, Double.NaNen C #…
Thanatos

Respuestas:

169

Sí, use math.nan.

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

Antes de Python 3.5, se podía usar float("nan")(no distingue entre mayúsculas y minúsculas).

Tenga en cuenta que comprobar si dos cosas que son NaN son iguales entre sí siempre devolverá falso. Esto se debe en parte a que no se puede decir (estrictamente hablando) que dos cosas que "no son un número" sean iguales entre sí; consulte ¿Cuál es el motivo de que todas las comparaciones devuelvan falsas para los valores de NaN IEEE754? para más detalles e información.

En su lugar, utilícelo math.isnan(...)si necesita determinar si un valor es NaN o no.

Además, la semántica exacta de la ==operación en el valor de NaN puede causar problemas sutiles al intentar almacenar NaN dentro de tipos de contenedores como listo dict(o cuando se utilizan tipos de contenedores personalizados). Consulte Comprobación de la presencia de NaN en un contenedor para obtener más detalles.


También puede construir números NaN usando el módulo decimal de 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(...) también funcionará con objetos Decimal.


Sin embargo, no puede construir números NaN en el módulo de fracciones de 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.

Por cierto, también puede hacer float('Inf'), Decimal('Inf')o math.inf(3.5+) para asignar números infinitos. (Y ver también math.isinf(...))

Sin embargo, hacerlo Fraction('Inf')o Fraction(float('inf'))no está permitido y generará una excepción, como NaN.

Si desea una forma rápida y fácil de verificar si un número no es NaN ni infinito, puede usarlo a math.isfinite(...)partir de Python 3.2+.


Si desea realizar comprobaciones similares con números complejos, el cmathmódulo contiene un conjunto similar de funciones y constantes que el mathmódulo:

Michael0x2a
fuente
2
Tenga en cuenta que usar float ('nan) es 3 veces más lento que usar np.nan, y aproximadamente 6.5 veces más lento que asignar nan = float (' nan ') una vez y luego usar la variable' nan 'para todas las asignaciones siguientes (como se sugiere en abarnert's responder).
Daniel Goldfarb
18
nan = float('nan')

Y ahora usted tiene la constante nan.

De manera similar, puede crear valores NaN para decimal.Decimal .:

dnan = Decimal('nan')
abarnert
fuente
Esta es la respuesta más eficiente para múltiples asignaciones nan: es decir, use float ('nan') solo una vez y luego use la constante asignada para todas las asignaciones restantes. Sin embargo, si solo está haciendo una o dos asignaciones de nan total, entonces usar numpy.nan es más rápido.
Daniel Goldfarb
7

Utilizar float("nan"):

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

Puede hacer float('nan')para obtener NaN.

BrenBarn
fuente
6

Puede obtener NaN de "inf - inf" y puede obtener "inf" de un número mayor que 2e308, por lo que generalmente usé:

>>> inf = 9e999
>>> inf
inf
>>> inf - inf
nan
Polegato Junior
fuente
3
Esta respuesta votó en contra irrazonablemente. Estoy escribiendo muchas pequeñas pruebas de análisis en archivos .txt y usando ast.literal_eval para obtener la parte de salida esperada. Es imposible llamar a float ('nan') allí, y esta respuesta fue útil para mí.
Vitalik Verhovodov
0

Una forma más consistente (y menos opaca) de generar inf y -inf es usar nuevamente float ():

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

Tenga en cuenta que el tamaño de un flotador varía según la arquitectura, por lo que probablemente sea mejor evitar el uso de números mágicos como 9e999, incluso si es probable que funcione.

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)
usuario3685621
fuente