Assegnare una variabile NaN in Python senza numpy


103

La maggior parte delle lingue ha una costante NaN che puoi usare per assegnare a una variabile il valore NaN. Python può farlo senza usare numpy?


1
C, C ++, java, C #, ocaml, fa parte di molti linguaggi.
zelinka

2
NaN, in C, è NAN; è una costante definita in math.h, a partire da C99. (Penso che sia giusto chiamare la versione standardizzata più recente del linguaggio come quella lingua. Quindi "C" è C11.) (Vedi stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in -c ); in C ++, è NANcosì, c'è anche nan(), nanf()e nanl(), anche se sono un po 'meno certo per quello che fanno. double.NaNin Java, Double.NaNin C #…
Thanatos

Risposte:


169

Sì, usa math.nan.

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

Prima di Python 3.5, si poteva usare float("nan")(case insensitive).

Nota che il controllo per vedere se due cose che sono NaN sono uguali tra loro restituirà sempre false. Ciò è in parte dovuto al fatto che due cose che "non sono un numero" non possono (in senso stretto) essere considerate uguali tra loro - vedere Qual è il motivo per cui tutti i confronti restituiscono false per i valori NaN IEEE754? per maggiori dettagli e informazioni.

Utilizzare invece math.isnan(...)se è necessario determinare se un valore è NaN o meno.

Inoltre, la semantica esatta ==dell'operazione sul valore NaN può causare problemi sottili quando si tenta di archiviare NaN all'interno di tipi di contenitori come listo dict(o quando si utilizzano tipi di contenitori personalizzati). Vedere Verifica della presenza NaN in un contenitore per ulteriori dettagli.


Puoi anche costruire numeri NaN usando il modulo decimale di 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(...) funzionerà anche con oggetti Decimal.


Tuttavia, non puoi costruire numeri NaN nel modulo delle frazioni di 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.

Per inciso, puoi anche fare float('Inf'), Decimal('Inf')o math.inf(3.5+) per assegnare numeri infiniti. (E vedi anche math.isinf(...))

Tuttavia, fare Fraction('Inf')o Fraction(float('inf'))non è consentito e genererà un'eccezione, proprio come NaN.

Se vuoi un modo semplice e veloce per verificare se un numero non è né NaN né infinito, puoi usarlo a math.isfinite(...)partire da Python 3.2+.


Se vuoi eseguire controlli simili con numeri complessi, il cmathmodulo contiene un insieme di funzioni e costanti simile al mathmodulo:


2
Si noti che l'uso di float ('nan) è 3 volte più lento dell'uso di np.nan e circa 6,5 ​​volte più lento dell'assegnazione di nan = float (' nan ') una volta e quindi dell'uso della variabile' nan 'per tutti i seguenti incarichi (come suggerito in abarnert's risposta).
Daniel Goldfarb

18
nan = float('nan')

E ora avete la costante, nan.

Allo stesso modo è possibile creare valori NaN per decimal.Decimal .:

dnan = Decimal('nan')

Questa è la risposta più efficiente per più assegnazioni nan: ovvero, usa float ('nan') solo una volta, quindi usa la costante assegnata per tutti gli incarichi rimanenti. Tuttavia, se stai eseguendo solo uno o due incarichi di nan totale, usare numpy.nan è il più veloce.
Daniel Goldfarb

7

Usa float("nan"):

>>> float("nan")
nan


6

Puoi ottenere NaN da "inf - inf" e puoi ottenere "inf" da un numero maggiore di 2e308, quindi generalmente ho usato:

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

3
Questa risposta è stata svalutata in modo irragionevole. Sto scrivendo molti piccoli test di analisi nei file .txt e utilizzo ast.literal_eval per ottenere la parte di output prevista. È impossibile chiamare float ('nan') lì, e questa risposta è stata utile per me.
Vitalik Verhovodov

0

Un modo più coerente (e meno opaco) per generare inf e -inf è usare nuovamente float ():

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

Nota che la dimensione di un float varia a seconda dell'architettura, quindi probabilmente è meglio evitare di usare numeri magici come 9e999, anche se è probabile che funzioni.

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.