Respuestas:
Todavía puede obtener valores que no sean un número (NaN) a partir de aritmética simple que involucra inf
:
>>> 0 * float("inf")
nan
Tenga en cuenta que normalmente no obtendrá un inf
valor a través de los 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 inf
valor se considera un valor muy especial con una semántica inusual, por lo que es mejor saber de OverflowError
inmediato a través de una excepción, en lugar de tener un inf
valor silenciosamente inyectado en sus cálculos.
**
parece un poco defectuoso. Cuando se desborda con números reales, arroja un error, pero cuando cualquiera de sus operandos es inf
o -inf
, devuelve 0.0
o inf
. Por lo que hace el trabajo correctamente cuando la entrada es inifinty, pero no cuando el resultado debe ser infinito.
La implementación de Python sigue el estándar IEEE-754 bastante bien, que puede usar como guía, pero se basa en el sistema subyacente en el que se compiló, por lo que pueden producirse diferencias de plataforma . Recientemente¹, se ha aplicado una solución que permite "infinito" así como "inf" , pero aquí es de menor importancia.
Las siguientes secciones se aplican igualmente a cualquier lenguaje que implemente la aritmética de coma flotante IEEE correctamente, no es específico solo de Python.
Cuando se trata >
de <
operadores infinitos y mayores o menores que , lo siguiente cuenta:
+inf
es mayor que-inf
-inf
es inferior a+inf
+inf
no es ni más alto ni más bajo que+inf
-inf
no es ni más alto ni más bajo que -inf
NaN
es falsa ( inf
no es mayor ni menor que NaN
)Cuando se compara para igualdad, +inf
y +inf
son iguales, como son -inf
y -inf
. Este es un tema muy debatido y puede sonar controvertido para usted, pero está en el estándar IEEE y Python se comporta así.
Por supuesto, +inf
es desigual -inf
y todo, incluido él NaN
mismo, es desigual NaN
.
La mayoría de los cálculos con infinito producirán infinito, a menos que ambos operandos sean infinitos, cuando la división o módulo de operación, o con multiplicación con cero, hay algunas reglas especiales a tener en cuenta:
NaN
0.0
o -0.0
².NaN
.inf - inf
, el resultado es indefinido: NaN
;inf - -inf
, el resultado es inf
;-inf - inf
, el resultado es -inf
;-inf - -inf
, el resultado es indefinido: NaN
.inf + inf
, el resultado es inf
;inf + -inf
, el resultado es indefinido: NaN
;-inf + inf
, el resultado es indefinido: NaN
;-inf + -inf
, el resultado es -inf
.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 ajustarse a un flotador de doble precisión (debería devolver infinito), pero cuando la entrada es inf
o -inf
, se comporta correctamente y devuelve inf
o 0.0
. Cuando el segundo argumento es NaN
, regresa NaN
, a menos que el primer argumento sea 1.0
. Hay más problemas, no todos cubiertos en los documentos .math.exp
sufre los mismos problemas que math.pow
. Una solución para solucionar esto por desbordamiento es usar un código similar a este:
try:
res = math.exp(420000)
except OverflowError:
res = float('inf')
Nota 1: como advertencia adicional, según lo definido por el estándar IEEE, si el resultado de su cálculo se desborda o desborda, el resultado no será un error de desbordamiento o desbordamiento, sino infinito positivo o negativo: 1e308 * 10.0
rendimientos inf
.
Nota 2: debido a que cualquier cálculo con NaN
retornos NaN
y cualquier comparación con NaN
, incluido él NaN
mismo false
, debe usar la math.isnan
función para determinar si un número es realmente NaN
.
Nota 3: aunque Python admite la escritura float('-NaN')
, el signo se ignora porque no existe ningún signo NaN
interno. Si divide -inf / +inf
, el resultado es que NaN
no -NaN
(no existe tal cosa).
Nota 4: tenga cuidado de confiar en cualquiera de los anteriores, ya que Python se basa en la biblioteca C o Java para la que fue compilada 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, por lo tanto: x / float('inf')
mantiene su signo y -1 / float('inf')
rendimientos -0.0
, 1 / float(-inf)
rendimientos -0.0
, 1 / float('inf')
rendimientos 0.0
y -1/ float(-inf)
rendimientos 0.0
. Además, 0.0 == -0.0
es necesariotrue
verificar manualmente el signo si no desea que sea cierto.
-1 * float('infinity') == -inf
También lo hace C99 .
La representación de coma 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 de lo que debe preocuparse: algunas operaciones aritméticas pueden causar excepciones / trampas de coma flotante, pero estas no se limitan solo a estas constantes "interesantes".
OverflowError
.
Encontré una advertencia que nadie hasta ahora ha mencionado. No sé si se presentará a menudo en situaciones prácticas, pero aquí es en aras de la integridad.
Por lo general, el cálculo de un número de módulo de infinito se devuelve como flotante, pero una fracción de módulo de infinito se devuelve nan
(no un número). 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 .
Actualización: esto se solucionará en Python 3.8 .
UNA CUEVA MUY MALA: División por cero
en una 1/x
fracción, hasta x = 1e-323
que es inf
pero cuando x = 1e-324
o poco arrojaZeroDivisionError
>>> 1/1e-323
inf
>>> 1/1e-324
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero
así que ten cuidado!
1e309
se interpretará como+inf
y-1e309
se interpretará como-inf
.