Assigner une variable NaN en python sans numpy

103

La plupart des langages ont une constante NaN que vous pouvez utiliser pour attribuer à une variable la valeur NaN. Python peut-il faire cela sans utiliser numpy?

zelinka
la source
1
C, C ++, java, C #, ocaml, ça fait partie de beaucoup de langages.
zelinka
2
NaN, en C, est NAN; c'est une constante définie dans math.h, à partir de C99. (Je pense qu'il est juste d'appeler la version standardisée la plus récente du langage comme ce langage. Ainsi "C" est C11.) (Voir stackoverflow.com/questions/1923837/how-to-use-nan-and-inf-in -c ); en C ++, c'est NANaussi, il y a aussi nan(), nanf()et nanl(), bien que je sois un peu moins sûr de ce qu'ils font. double.NaNen Java, Double.NaNen C #…
Thanatos

Réponses:

169

Oui - utilisez math.nan.

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

Avant Python 3.5, on pouvait utiliser float("nan")(insensible à la casse).

Notez que vérifier si deux choses qui sont NaN sont égales l'une à l'autre retournera toujours false. Ceci est en partie dû au fait que deux choses qui ne sont "pas un nombre" ne peuvent (à proprement parler) être égales l'une à l'autre - voir Quelle est la justification de toutes les comparaisons retournant false pour les valeurs NaN IEEE754? pour plus de détails et d'informations.

À la place, utilisez math.isnan(...)si vous avez besoin de déterminer si une valeur est NaN ou non.

En outre, la sémantique exacte de l' ==opération sur la valeur NaN peut entraîner des problèmes subtils lors de la tentative de stockage de NaN dans des types de conteneurs tels que listou dict(ou lors de l'utilisation de types de conteneurs personnalisés). Voir Vérification de la présence de NaN dans un conteneur pour plus de détails.


Vous pouvez également construire des nombres NaN en utilisant le module décimal 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(...) fonctionnera également avec les objets Decimal.


Cependant, vous ne pouvez pas construire de nombres NaN dans le module de fractions 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.

Incidemment, vous pouvez également faire float('Inf'), Decimal('Inf')ou math.inf(3.5+) pour attribuer des nombres infinis. (Et voir aussi math.isinf(...))

Cependant faire Fraction('Inf')ou Fraction(float('inf'))n'est pas autorisé et lèvera une exception, tout comme NaN.

Si vous voulez un moyen rapide et facile de vérifier si un nombre n'est ni NaN ni infini, vous pouvez l'utiliser à math.isfinite(...)partir de Python 3.2+.


Si vous souhaitez effectuer des vérifications similaires avec des nombres complexes, le cmathmodule contient un ensemble de fonctions et de constantes similaire au mathmodule:

Michael0x2a
la source
2
Notez que l'utilisation de float ('nan) est 3 fois plus lente que d'utiliser np.nan, et environ 6,5 fois plus lente que d'attribuer une fois nan = float (' nan '), puis d'utiliser la variable' nan 'pour toutes les affectations suivantes (comme suggéré dans abarnert's répondre).
Daniel Goldfarb
18
nan = float('nan')

Et maintenant , vous avez la constante, nan.

Vous pouvez également créer des valeurs NaN pour decimal.

dnan = Decimal('nan')
Abarnert
la source
C'est la réponse la plus efficace pour plusieurs affectations nan: c'est-à-dire, n'utilisez float ('nan') qu'une seule fois, puis utilisez la constante affectée pour toutes les affectations restantes. Cependant, si vous ne faites qu'une ou deux affectations de nan total, l'utilisation de numpy.nan est la plus rapide.
Daniel Goldfarb
7

Utilisez float("nan"):

>>> float("nan")
nan
orlp
la source
6

Vous pouvez faire float('nan')pour obtenir NaN.

BrenBarn
la source
6

Vous pouvez obtenir NaN à partir de "inf - inf", et vous pouvez obtenir "inf" à partir d'un nombre supérieur à 2e308, donc, j'ai généralement utilisé:

>>> inf = 9e999
>>> inf
inf
>>> inf - inf
nan
Polegato junior
la source
3
Cette réponse a été rejetée de manière déraisonnable. J'écris beaucoup de petits tests d'analyse dans des fichiers .txt et j'utilise ast.literal_eval pour obtenir la partie de sortie attendue. Il est impossible d'appeler float ('nan') là-bas, et cette réponse m'a été utile.
Vitalik Verhovodov
0

Une manière plus cohérente (et moins opaque) de générer inf et -inf consiste à utiliser à nouveau float ():

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

Notez que la taille d'un flotteur varie en fonction de l'architecture, il est donc préférable d'éviter d'utiliser des nombres magiques comme 9e999, même si cela est susceptible de fonctionner.

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
la source