float - inf python
Python Infinity-¿Alguna advertencia? (4)
Entonces Python tiene infinito positivo y negativo:
float("inf"), float("-inf")
Esto simplemente parece ser el tipo de característica que tiene que tener alguna advertencia. ¿Hay algo que deba saber?
Aún puede obtener valores de no-número (NaN) de aritmética simple que involucre inf
:
>>> 0 * float("inf")
nan
Tenga en cuenta que normalmente no obtendrá un valor inf
través de cálculos aritméticos habituales:
>>> 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'')
El valor inf
se considera un valor muy especial con una semántica inusual, por lo que es mejor saber sobre un OverflowError
directamente a través de una excepción, en lugar de tener un valor inf
inyectado silenciosamente en sus cálculos.
Encontré una advertencia que nadie hasta ahora ha mencionado. No sé si surgirá a menudo en situaciones prácticas, pero lo estoy planteando aquí para completar.
El cálculo de una fracción de módulo infinito causa un resultado de nan
(no un número), en lugar de producir los resultados habituales de modificar un número por infinito. Aquí hay un ejemplo:
>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction(''1/3'') % inf
nan
Archivé un problema en el rastreador de errores de Python. Se puede ver en https://bugs.python.org/issue32968 .
Lo mismo ocurre con C99 .
La representación de punto flotante IEEE 754 utilizada por todos los procesadores modernos tiene varios patrones de bits especiales reservados para infinito positivo (signo = 0, exp = ~ 0, frac = 0), infinito negativo (signo = 1, exp = ~ 0, frac = 0 ), y muchos NaN (No es un número: exp = ~ 0, frac ≠ 0).
Todo lo que necesita para preocuparse: algunos cálculos aritméticos pueden causar excepciones / trampas de coma flotante, pero estos no están limitados solo a estas constantes "interesantes".
La implementación de Python sigue bastante bien el estándar IEEE-754 , que puede usar como guía, pero se basa en el sistema subyacente en el que se compiló, por lo que pueden ocurrir diferencias en la plataforma . Recientemente¹, se ha aplicado una solución que permite "infinito" e "inf" , pero eso es de menor importancia aquí.
Las siguientes secciones se aplican igualmente a cualquier lenguaje que implemente la aritmética de punto flotante IEEE correctamente, no es específico solo para Python.
Comparación de la desigualdad
Cuando se trata de infinito y operadores mayores que >
o menores que <
, lo siguiente cuenta:
- cualquier número que incluya
+inf
es más alto que-inf
- cualquier número que incluya
-inf
sea menor que+inf
-
+inf
no es ni más alto ni más bajo que+inf
-
-inf
no es ni más ni menos que-inf
- cualquier comparación que involucre
NaN
es falsa (inf
no es ni más alta ni más baja queNaN
)
Comparación para la igualdad
Cuando se compara por igualdad, +inf
e +inf
son iguales, como son -inf
y -inf
. Este es un tema muy debatido y puede sonar controversial para ti, pero está en el estándar IEEE y Python se comporta así.
Por supuesto, +inf
es -inf
a -inf
y todo, incluido el propio NaN
, no es igual a NaN
.
Cálculos con infinito
La mayoría de los cálculos con infinito arrojarán infinito, a menos que ambos operandos sean infinitos, cuando la división o módulo de operación, o con la multiplicación con cero, haya algunas reglas especiales a tener en cuenta:
- cuando se multiplica por cero, para lo cual el resultado no está definido, produce
NaN
- al dividir cualquier número (excepto el infinito mismo) por infinito, que arroja
0.0
o-0.0
². - al dividir (incluido el módulo) el infinito positivo o negativo por el infinito positivo o negativo, el resultado no está definido, por lo que
NaN
. - al restar, los resultados pueden ser sorprendentes, pero siguen el sentido matemático común :
- al hacer
inf - inf
, el resultado no está definido:NaN
; - al hacer
inf - -inf
, el resultado esinf
; - al hacer
-inf - inf
, el resultado es-inf
; - al hacer
-inf - -inf
, el resultado no está definido:NaN
.
- al hacer
- cuando se agrega, también puede ser sorprendente:
- al hacer
inf + inf
, el resultado esinf
; - al hacer
inf + -inf
, el resultado no está definido:NaN
; - al hacer
-inf + inf
, el resultado no está definido:NaN
; - al hacer
-inf + -inf
, el resultado es-inf
.
- al hacer
- usar
math.pow
,pow
o**
es complicado, ya que no se comporta como debería. Lanza una excepción de desbordamiento cuando el resultado con dos números reales es demasiado alto para caber en un flotador de doble precisión (debe regresar al infinito), pero cuando la entrada esinf
o-inf
, se comporta correctamente y devuelveinf
o0.0
. Cuando el segundo argumento esNaN
, devuelveNaN
, a menos que el primer argumento sea1.0
. Hay más problemas, no todos cubiertos en los documentos . math.exp
sufre los mismos problemas quemath.pow
. Una solución para arreglar esto para el desbordamiento es usar un código similar a este:try: res = math.exp(420000) except OverflowError: res = float(''inf'')
Notas
Nota 1: como una advertencia adicional, tal como lo define el estándar IEEE, si el resultado de su cálculo se desborda o sobrepasa, el resultado no será un error de subdesbordamiento o desbordamiento, sino un infinito positivo o negativo: 1e308 * 10.0
arroja inf
.
Nota 2: dado que cualquier cálculo con NaN
devuelve NaN
y cualquier comparación con NaN
, incluido el propio NaN
, es false
, debe usar la función math.isnan
para determinar si un número es realmente NaN
.
Nota 3: a pesar de que Python admite escribir float(''-NaN'')
, el signo se ignora, porque no existe ningún signo en NaN
internamente. Si divide -inf / +inf
, el resultado es NaN
, no -NaN
(no existe tal cosa).
Nota 4: tenga cuidado de confiar en cualquiera de los anteriores, ya que Python confía en la biblioteca C o Java para la que se compiló y no todos los sistemas subyacentes implementan todo este comportamiento correctamente. Si quieres estar seguro, prueba el infinito antes de hacer tus cálculos.
¹) Recientemente significa desde la versión 3.2 .
²) Los puntos flotantes admiten cero positivo y negativo, entonces: x / float(''inf'')
mantiene su signo y -1 / float(''inf'')
produce -0.0
, 1 / float(-inf)
produce -0.0
, 1 / float(''inf'')
produce 0.0
y -1/ float(-inf)
rinde 0.0
. Además, 0.0 == -0.0
es true
, debe verificar manualmente el letrero si no desea que sea verdadero.