Atribuindo uma variável NaN em python sem numpy


103

A maioria das linguagens tem uma constante NaN que você pode usar para atribuir o valor NaN a uma variável. O python pode fazer isso sem usar o numpy?


1
C, C ++, java, C #, ocaml, faz parte de muitas linguagens.
zelinka de

2
NaN, em C, é NAN; é uma constante definida em math.h, a partir de C99. (Acho que é justo chamar a versão padronizada mais recente da linguagem como essa linguagem. Portanto, "C" é C11.) (Consulte stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in -c ); em C ++, é NANassim, há também nan(), nanf()e nanl(), embora eu sou um pouco menos certo sobre o que eles fazem. double.NaNem Java, Double.NaNem C #…
Thanatos

Respostas:


169

Sim - use math.nan.

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

Antes do Python 3.5, podia-se usar float("nan")(não diferencia maiúsculas de minúsculas).

Observe que verificar se duas coisas que são NaN são iguais uma à outra sempre retornará falso. Isso ocorre em parte porque duas coisas que "não são um número" não podem (estritamente falando) ser iguais uma à outra - consulte Qual é a razão para todas as comparações retornarem falso para valores IEEE754 NaN? para mais detalhes e informações.

Em vez disso, use math.isnan(...)se precisar determinar se um valor é NaN ou não.

Além disso, a semântica exata da ==operação no valor NaN pode causar problemas sutis ao tentar armazenar NaN dentro de tipos de contêiner como listou dict(ou ao usar tipos de contêiner personalizados). Consulte Verificando a presença de NaN em um contêiner para obter mais detalhes.


Você também pode construir números NaN usando o módulo decimal do 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(...) também funcionará com objetos decimais.


No entanto, você não pode construir números NaN no módulo de frações do 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.

Aliás, você também pode fazer float('Inf'), Decimal('Inf')ou math.inf(3.5+) para atribuir um número infinito. (E veja também math.isinf(...))

No entanto, fazer Fraction('Inf')ou Fraction(float('inf'))não é permitido e lançará uma exceção, assim como NaN.

Se você deseja uma maneira rápida e fácil de verificar se um número não é NaN nem infinito, você pode usar a math.isfinite(...)partir do Python 3.2+.


Se você quiser fazer verificações semelhantes com números complexos, o cmathmódulo contém um conjunto de funções e constantes semelhantes ao mathmódulo:


2
Observe que usar float ('nan) é 3x mais lento do que usar np.nan e cerca de 6,5 vezes mais lento do que atribuir nan = float (' nan ') uma vez e, em seguida, usar a variável' nan 'para todas as atribuições seguintes (como sugerido no artigo de abarnert responda).
Daniel Goldfarb

18
nan = float('nan')

E agora você tem a constante nan,.

Da mesma forma, você pode criar valores NaN para decimal.Decimal .:

dnan = Decimal('nan')

Esta é a resposta mais eficiente para várias atribuições nan: ou seja, use float ('nan') apenas uma vez e, em seguida, use a constante atribuída para todas as atribuições restantes. No entanto, se você estiver fazendo apenas uma ou duas atribuições de nan no total, usar numpy.nan é o mais rápido.
Daniel Goldfarb

7

Use float("nan"):

>>> float("nan")
nan


6

Você pode obter NaN de "inf - inf", e você pode obter "inf" de um número maior que 2e308, então, geralmente usei:

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

3
Esta resposta foi reprovada irracionalmente. Estou escrevendo muitos pequenos testes de análise em arquivos .txt e usando ast.literal_eval para obter a parte de saída esperada. É impossível chamar float ('nan') aqui, e essa resposta foi útil para mim.
Vitalik Verhovodov

0

Uma maneira mais consistente (e menos opaca) de gerar inf e -inf é usar novamente float ():

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

Observe que o tamanho de um float varia dependendo da arquitetura, portanto, provavelmente é melhor evitar o uso de números mágicos como 9e999, mesmo que isso 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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.