Réponses:
Vous pouvez toujours obtenir des valeurs not-a-number (NaN) à partir de l'arithmétique simple impliquant inf
:
>>> 0 * float("inf")
nan
Notez que vous normalement pas obtenir une inf
valeur 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 inf
valeur 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 OverflowError
immédiatement une exception, plutôt que d'avoir une inf
valeur injectée silencieusement dans vos calculs.
**
semble un peu bogué. Lorsqu'il déborde de nombres réels, il renvoie une erreur, mais lorsque l'un de ses opérandes est inf
ou -inf
, il renvoie soit 0.0
ou inf
. Ainsi , il fait correctement lorsque l'entrée est inifinty, mais pas lorsque le résultat devrait être infini.
L'implémentation de Python suit assez bien la norme IEEE-754 , que vous pouvez utiliser comme guide, mais elle repose sur le système sous-jacent sur lequel elle a été compilée, de sorte que des différences de plate-forme peuvent survenir. Récemment¹, un correctif a été appliqué qui autorise «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 en virgule flottante IEEE, il n'est pas spécifique à Python.
Lorsqu'il s'agit >
d' <
opérateurs infini et supérieur ou inférieur à , 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érieure, ni inférieure à NaN
)Lorsqu'on les compare pour l'égalité, +inf
et +inf
sont égaux, comme le sont -inf
et -inf
. C'est une question très débattue et peut sembler controversée pour vous, mais c'est dans la norme IEEE et Python se comporte comme ça.
Bien sûr, +inf
est inégal à -inf
et tout, y compris NaN
lui-même, est inégal à NaN
.
La plupart des calculs avec l'infini donneront l'infini, sauf si les deux opérandes sont l'infini, lorsque l'opération division ou modulo, ou avec une multiplication avec zéro, il y a quelques règles spéciales à garder à l'esprit:
NaN
0.0
ou -0.0
².NaN
.inf - inf
, le résultat est indéfini: NaN
;inf - -inf
, le résultat est inf
;-inf - inf
, le résultat est -inf
;-inf - -inf
, le résultat est indéfini: NaN
.inf + inf
, le résultat est inf
;inf + -inf
, le résultat est indéfini: NaN
;-inf + inf
, le résultat est indéfini: NaN
;-inf + -inf
, 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 s'adapter à un flotteur double précision (il doit renvoyer l'infini), mais lorsque l'entrée est inf
ou -inf
, il se comporte correctement et renvoie soit inf
ou 0.0
. Lorsque le deuxième argument est NaN
, il retourne NaN
, sauf si le premier argument est 1.0
. Il y a plus de problèmes, pas tous traités dans la documentation .math.exp
souffre des mêmes problèmes que math.pow
. Une solution pour résoudre ce problème en cas de débordement consiste à utiliser un code similaire à celui-ci:
try:
res = math.exp(420000)
except OverflowError:
res = float('inf')
Note 1: comme une mise en garde supplémentaire, que tel que défini par la norme IEEE, si le résultat de votre calcul sous-ou déborde, le résultat ne sera pas une erreur de sous-ou de débordement, mais l'infini positif ou négatif: 1e308 * 10.0
cède inf
.
Remarque 2: étant donné que tout calcul avec des NaN
retours NaN
et toute comparaison à NaN
, y compris NaN
lui-même false
, vous devez utiliser la math.isnan
fonction pour déterminer si un nombre est effectivement NaN
.
Remarque 3: bien que Python prenne en charge l'écriture float('-NaN')
, le signe est ignoré, car il n'existe pas de connexion en NaN
interne. Si vous divisez -inf / +inf
, le résultat est NaN
non -NaN
(il n'y a rien de tel).
Remarque 4: veillez à vous fier à l'un des éléments ci-dessus, car Python s'appuie sur la bibliothèque C ou Java pour laquelle il a été compilé et tous les systèmes sous-jacents n'implémentent pas correctement tout ce comportement. Si vous voulez être sûr, testez l'infini avant de faire vos calculs.
¹) signifie récemment depuis la version 3.2 .
²) Les virgules flottantes supportent le zéro positif et négatif, donc: x / float('inf')
garde son signe et les -1 / float('inf')
rendements -0.0
, les 1 / float(-inf)
rendements -0.0
, les 1 / float('inf')
rendements 0.0
et les -1/ float(-inf)
rendements 0.0
. En outre, 0.0 == -0.0
quelstrue
, vous devez vérifier manuellement le signe si vous ne voulez pas que ce soit vrai.
-1 * float('infinity') == -inf
Il en va de même pour C99 .
La représentation en virgule flottante IEEE 754 utilisée par tous les processeurs modernes a plusieurs modèles de bits spéciaux réservés pour l'infini positif (signe = 0, exp = ~ 0, frac = 0), l'infini négatif (signe = 1, exp = ~ 0, frac = 0 ), et de nombreux NaN (Pas un nombre: exp = ~ 0, frac ≠ 0).
Tout ce dont vous devez vous inquiéter: certaines arithmétiques peuvent provoquer des exceptions / interruptions en virgule flottante, mais celles-ci ne sont pas limitées à ces constantes «intéressantes».
OverflowError
.
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 ici, c'est par souci d'exhaustivité.
Habituellement, le calcul d'un nombre modulo infinity se retourne lui-même sous forme de flottant, 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 déposé un problème sur le traqueur de bogues Python. Il peut être vu à https://bugs.python.org/issue32968 .
Mise à jour: cela sera corrigé dans Python 3.8 .
UN TRÈS MAUVAIS CAVEAT: Division by Zero
en une 1/x
fraction, jusqu'à x = 1e-323
c'est inf
mais quand x = 1e-324
ou peu il jetteZeroDivisionError
>>> 1/1e-323
inf
>>> 1/1e-324
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero
alors soyez prudent!
1e309
sera interprétée comme+inf
et-1e309
sera interprétée comme-inf
.