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 infvaleur 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 infvaleur 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 OverflowErrorimmédiatement une exception, plutôt que d'avoir une infvaleur 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 infou -inf, il renvoie soit 0.0ou 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:
+infest supérieur à-inf-infest inférieur à+inf +infn'est ni supérieur ni inférieur à+inf-inf n'est ni supérieur ni inférieur à -infNaNest fausse ( infn'est ni supérieure, ni inférieure à NaN)Lorsqu'on les compare pour l'égalité, +infet +infsont égaux, comme le sont -infet -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, +infest inégal à -infet tout, y compris NaNlui-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:
NaN0.0ou -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, powou **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 infou -inf, il se comporte correctement et renvoie soit infou 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.expsouffre 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.0cède inf.
Remarque 2: étant donné que tout calcul avec des NaNretours NaNet toute comparaison à NaN, y compris NaNlui-même false, vous devez utiliser la math.isnanfonction 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 NaNinterne. Si vous divisez -inf / +inf, le résultat est NaNnon -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.0et les -1/ float(-inf)rendements 0.0. En outre, 0.0 == -0.0quelstrue , 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/xfraction, jusqu'à x = 1e-323c'est infmais quand x = 1e-324ou 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!
1e309sera interprétée comme+infet-1e309sera interprétée comme-inf.