Question Python Infinity - Des réserves?


Donc Python a l'infini positif et négatif:

float("inf"), float("-inf")

Cela semble être le type de fonctionnalité qui doit faire l’objet d’une mise en garde. Y a-t-il quelque chose que je devrais savoir?


163
2017-10-27 00:12


origine


Réponses:


Vous pouvez toujours obtenir des valeurs sans nombre (NaN) à partir de l'arithmétique simple impliquant inf:

>>> 0 * float("inf")
nan

Notez que vous allez normalement ne pas obtenir un inf valeur par des calculs arithmétiques habituels:

>>> 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')

le 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 un OverflowError immédiatement par une exception, plutôt que d'avoir un inf valeur injectée silencieusement dans vos calculs.


92
2017-10-27 00:31



Implémentation de Python suit le Norme IEEE-754 assez bien, que vous pouvez utiliser comme guide, mais il repose sur le système sous-jacent sur lequel il a été compilé, donc différences de plate-forme peut se produire. Récemment¹, un correctif a été appliqué qui permet "infini" aussi bien que "inf", mais cela a peu d'importance ici.

Les sections suivantes s'appliquent également à tout langage qui implémente l'arithmétique à virgule flottante IEEE correctement, il n'est pas spécifique à Python.

Comparaison pour l'inégalité

Lorsque vous traitez avec l'infini et plus grand que > ou moins que < opérateurs, les chiffres suivants:

  • n'importe quel nombre y compris +inf est plus élevé que -inf
  • n'importe quel nombre y compris -inf est inférieur à +inf 
  • +inf est ni plus haut ni plus bas que +inf
  • -inf n'est ni supérieur ni inférieur à -inf
  • toute comparaison impliquant NaN c'est faux (inf n'est ni plus élevé ni inférieur à NaN)

Comparaison pour l'égalité

Lorsque comparé pour l'égalité, +inf et +inf sont égaux, comme sont -inf et -inf. Ceci est un problème très controversé et peut vous sembler controversé, mais il se trouve dans la norme IEEE et Python se comporte comme ça.

Bien sûr, +inf est inégal à -inf et tout, y compris NaN elle-même, est inégale NaN.

Calculs à l'infini

La plupart des calculs avec l'infini produiront l'infini, sauf si les deux opérandes sont infinis, quand la division d'opération ou modulo, ou avec la multiplication avec zéro, il y a des règles spéciales à garder à l'esprit:

  • multiplié par zéro, pour lequel le résultat est indéfini, il cède NaN
  • en divisant un nombre quelconque (sauf l'infini lui-même) par l'infini, ce qui donne 0.0 ou -0.0².
  • en divisant (y compris modulo) l'infini positif ou négatif par l'infini positif ou négatif, le résultat est indéfini, donc NaN.
  • en soustrayant, les résultats peuvent être surprenants, mais suivez sens commun des mathématiques:
    • en faisant inf - inf, le résultat est indéfini: NaN;
    • en faisant inf - -inf, le résultat est inf;
    • en faisant -inf - inf, le résultat est -inf;
    • en faisant -inf - -inf, le résultat est indéfini: NaN.
  • en ajoutant, cela peut aussi être surprenant:
    • en faisant inf + inf, le résultat est inf;
    • en faisant inf + -inf, le résultat est indéfini: NaN;
    • en faisant -inf + inf, le résultat est indéfini: NaN;
    • en faisant -inf + -inf, le résultat est -inf.
  • en utilisant math.pow, pow ou ** est délicat, car il ne se comporte pas comme il se doit. Il jette une exception de dépassement lorsque le résultat avec deux nombres réels est trop élevé pour contenir un flottant double précision (il doit retourner l’infini), mais lorsque l’entrée est inf ou -inf, il se comporte correctement et retourne soit inf ou 0.0. Lorsque le second argument est NaN, ça revient NaN, sauf si le premier argument est 1.0. Il y a plus de problèmes, pas tous couvert dans les docs.
  • 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')
    

Remarques

Note 1: En guise de mise en garde supplémentaire, comme défini par la norme IEEE, si votre calcul entraîne des débordements ou des débordements, le résultat ne sera pas une erreur de dépassement ou de dépassement, mais un infini positif ou négatif: 1e308 * 10.0 rendements inf.

Note 2: parce que tout calcul avec NaN résultats NaN et toute comparaison avec NaN, comprenant NaN lui-même est false, vous devriez utiliser le math.isnan fonction pour déterminer si un nombre est en effet NaN.

Note 3: bien que Python supporte l'écriture float('-NaN'), le signe est ignoré, car il n'existe aucun signe NaN intérieurement. Si vous divisez -inf / +inf, le résultat est NaN, ne pas -NaN (il n'y a pas une telle chose).

Note 4: veillez à vous fier à tout ce qui précède, 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 tous ce comportement correctement. Si vous voulez ê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, donc: x / float('inf') garde son signe et -1 / float('inf') rendements -0.0, 1 / float(-inf) rendements -0.0, 1 / float('inf') rendements 0.0 et -1/ float(-inf) rendements 0.0. En outre, 0.0 == -0.0 est true, vous devez vérifier manuellement le signe si vous ne voulez pas que ce soit vrai.


91
2017-10-27 00:33



Alors est-ce que C99.

La représentation en virgule flottante IEEE 754 utilisée par tous les processeurs modernes possède plusieurs modèles de bits spéciaux réservés à l'infini positif (signe = 0, exp = ~ 0, frac = 0), infini négatif (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 soucier: une arithmétique peut provoquer des exceptions / traps en virgule flottante, mais ceux-ci ne se limitent pas à ces constantes "intéressantes".


3
2017-10-27 00:25



J'ai trouvé une mise en garde que personne n'a mentionnée jusqu'à présent. Je ne sais pas si cela se produira souvent dans des situations pratiques, mais je le mets ici pour des raisons d'exhaustivité.

Calculer une fraction modulo infini provoque un résultat de nan (pas un nombre), au lieu de produire les résultats habituels de la modification d'un nombre par l'infini. 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. On peut le voir à https://bugs.python.org/issue32968.


1
2018-02-28 04:07