Donc, Python a l'infini positif et négatif:
float("inf"), float("-inf")
Cela semble être le type de fonctionnalité qui doit être mis en garde. Y a-t-il quelque chose que je devrais être au courant?
Vous pouvez toujours obtenir des valeurs non numériques (NaN) à partir d'une simple arithmétique impliquant inf
:
>>> 0 * float("inf")
nan
Notez que vous obtiendrez normalement pas une valeur inf
par des calculs arithmétiques usuels:
>>> 2.0**2
4.0
>>> _**2
16.0
>>> _**2
256.0
>>> _**2
65536.0
>>> _**2
4294967296.0
>>> _**2
1.8446744073709552e+19
>>> _**2
3.4028236692093846e+38
>>> _**2
1.157920892373162e+77
>>> _**2
1.3407807929942597e+154
>>> _**2
Traceback (most recent call last):
File "<stdin>", line 1, in ?
OverflowError: (34, 'Numerical result out of range')
La valeur inf
est considérée comme une valeur très spéciale avec une sémantique inhabituelle. Il est donc préférable de connaître immédiatement une OverflowError
via une exception, plutôt que d'avoir une valeur inf
injectée silencieusement dans vos calculs. .
L'implémentation de Python suit assez bien le standard IEEE-754 , que vous pouvez utiliser comme guide, mais elle repose sur le système sous-jacent sur lequel elle a été compilée. , donc différences de plate-forme peuvent se produire. Récemment¹, un correctif a été appliqué qui permet "l'infini" ainsi que "inf" , mais c'est d'une importance mineure ici.
Les sections suivantes s'appliquent également à tout langage qui implémente correctement l'arithmétique à virgule flottante IEEE; il n'est pas spécifique à Python.
Lorsqu’il s’agit d’opérateurs infini et supérieurs à >
ou inférieurs à <
, les éléments suivants comptent:
+inf
est supérieur à -inf
-inf
est inférieur à +inf
+inf
n'est ni supérieur ni inférieur à +inf
-inf
n'est ni supérieur ni inférieur à -inf
NaN
est fausse (inf
n'est ni supérieur ni inférieur à NaN
)Lorsque l'égalité est comparée, +inf
et +inf
sont égaux, de même que -inf
et -inf
. C’est une question très discutée et qui peut paraître controversée, mais elle est conforme à la norme IEEE et Python se comporte exactement comme cela.
Bien entendu, +inf
est différent de -inf
et tout, y compris NaN
lui-même, est différent de NaN
.
La plupart des calculs avec l'infini donneront l'infini, à moins que les deux opérandes ne soient l'infini, que l'opération division ou modulo, ou la multiplication par zéro, prévoient certaines règles spéciales:
NaN
0.0
ou -0.0
².NaN
.inf - inf
est exécuté, le résultat est indéfini: NaN
;inf - -inf
est exécuté, le résultat est inf
;-inf - inf
est exécuté, le résultat est -inf
;-inf - -inf
est exécuté, le résultat est indéfini: NaN
.inf + inf
est exécuté, le résultat est inf
;inf + -inf
est exécuté, le résultat est indéfini: NaN
;-inf + inf
est exécuté, le résultat est indéfini: NaN
;-inf + -inf
est exécuté, le résultat est -inf
.math.pow
, pow
ou **
est délicat, car il ne se comporte pas comme il se doit. Il lève une exception de dépassement de capacité lorsque le résultat avec deux nombres réels est trop élevé pour un flottant à double précision (il devrait renvoyer l'infini), mais lorsque l'entrée est inf
ou -inf
, il se comporte correctement et renvoie soit inf
, soit 0.0
. Lorsque le deuxième argument est NaN
, il renvoie NaN
, sauf si le premier argument est 1.0
. Il y a plus de problèmes, pas tous couverts dans la documentation .math.exp
souffre des mêmes problèmes que math.pow
. Une solution pour résoudre ce problème de débordement consiste à utiliser un code similaire à celui-ci:
try:
res = math.exp(420000)
except OverflowError:
res = float('inf')
Remarque 1: comme mise en garde supplémentaire, telle que définie par le standard IEEE, si le résultat de votre calcul est trop faible ou trop élevé, le résultat ne sera pas inférieur à - ou erreur de débordement, mais infini positif ou négatif: 1e308 * 10.0
donne inf
.
Remarque 2: , car tout calcul avec NaN
renvoie NaN
et toute comparaison avec NaN
, y compris NaN
lui-même est false
, vous devez utiliser le math.isnan
fonction pour déterminer si un nombre est bien NaN
.
Remarque 3: bien que Python prenne en charge l'écriture float('-NaN')
, le signe est ignoré, car il n'existe aucun signe NaN
en interne. . Si vous divisez -inf / +inf
, le résultat est NaN
et non pas -NaN
(cela n'existe pas).
Remarque 4: veillez à vous fier à l'un des éléments ci-dessus, car Python s'appuie sur le C ou Java. _ bibliothèque pour laquelle elle a été compilée et tous les systèmes sous-jacents n’implémentent pas correctement tout ce comportement. Si vous voulez en être sûr, testez l'infini avant de faire vos calculs.
¹) Récemment signifie depuis version 3.2 .
²) Les points flottants supportent le zéro positif et négatif, ainsi: x / float('inf')
conserve son signe et -1 / float('inf')
donne -0.0
, 1 / float(-inf)
donne -0.0
, 1 / float('inf')
donne 0.0
et -1/ float(-inf)
donne 0.0
. De plus, 0.0 == -0.0
EST true
, vous devez vérifier le signe manuellement si vous ne voulez pas qu'il soit vrai.
Ainsi fait C99 .
La représentation en virgule flottante IEEE 754 utilisée par tous les processeurs modernes comporte plusieurs modèles de bits spéciaux réservés aux infinis positifs (signe = 0, exp = ~ 0, frac = 0), infinis négatifs (signe = 1, exp = ~ 0, frac = 0). ), et beaucoup de NaN (pas un nombre: exp = ~ 0, frac 0).
Tout ce dont vous avez besoin de vous inquiéter: certaines arithmétiques peuvent causer des exceptions/pièges à virgule flottante, mais ceux-ci ne se limitent pas à ces constantes "intéressantes".
J'ai trouvé une mise en garde que personne n'a encore mentionnée. Je ne sais pas si cela se produira souvent dans des situations pratiques, mais le voici par souci d'exhaustivité.
Généralement, le calcul d’un nombre modulo infini se retourne sous forme de float, mais une fraction modulo infinity renvoie nan
(pas un nombre). Voici un exemple:
>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction('1/3') % inf
nan
J'ai signalé un problème sur le traqueur de bogues Python. On peut le voir à https://bugs.python.org/issue32968 .
Mise à jour: ce sera corrigé dans Python 3.8 .