Respostas:
Você ainda pode obter valores não-numéricos (NaN) a partir de aritmética simples, envolvendo inf
:
>>> 0 * float("inf")
nan
Observe que você normalmente não obterá um inf
valor através de cálculos aritméticos usuais:
>>> 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')
O inf
valor é considerado um valor muito especial com semântica incomum; portanto, é melhor saber OverflowError
imediatamente sobre uma exceção, em vez de ter um inf
valor injetado silenciosamente em seus cálculos.
**
parece um buggy. Quando transborda com números reais, gera um erro, mas quando qualquer um de seus operandos é inf
or -inf
, ele retorna 0.0
ou inf
. Por isso, faz trabalho corretamente quando a entrada é inifinty, mas não quando o resultado deve ser infinito.
A implementação do Python segue muito bem o padrão IEEE-754 , que você pode usar como orientação, mas depende do sistema subjacente no qual foi compilado, para que possam ocorrer diferenças de plataforma . Recentemente¹, foi aplicada uma correção que permite "infinito" e "inf" , mas isso é de menor importância aqui.
As seções a seguir se aplicam igualmente a qualquer linguagem que implemente a aritmética de ponto flutuante IEEE corretamente, não sendo específica apenas para Python.
Ao lidar com operadores infinito e maior >
ou menor que o <
, o seguinte conta:
+inf
é maior que-inf
-inf
é menor que+inf
+inf
não é maior nem menor que+inf
-inf
não é maior nem menor que -inf
NaN
é falsa ( inf
não é maior nem menor que NaN
)Quando comparado por igualdade, +inf
e +inf
são iguais, como são -inf
e -inf
. Esse é um problema muito debatido e pode parecer controverso para você, mas está no padrão IEEE e o Python se comporta exatamente assim.
É claro que +inf
é desigual -inf
e tudo, inclusive NaN
ele próprio, é desigual NaN
.
A maioria dos cálculos com infinito produzirá infinito, a menos que ambos os operandos sejam infinitos, quando a divisão ou módulo de operação ou com multiplicação com zero, existem algumas regras especiais a serem lembradas:
NaN
0.0
ou -0.0
².NaN
.inf - inf
, o resultado é indefinido: NaN
;inf - -inf
, o resultado é inf
;-inf - inf
, o resultado é -inf
;-inf - -inf
, o resultado é indefinido: NaN
.inf + inf
, o resultado é inf
;inf + -inf
, o resultado é indefinido: NaN
;-inf + inf
, o resultado é indefinido: NaN
;-inf + -inf
, o resultado é -inf
.math.pow
, pow
ou **
é complicado, pois não se comporta como deveria. Ele lança uma exceção de estouro quando o resultado com dois números reais é muito alto para caber em uma flutuação de precisão dupla (deve retornar infinito), mas quando a entrada é inf
ou -inf
, ela se comporta corretamente e retorna inf
ou 0.0
. Quando o segundo argumento é NaN
, ele retorna NaN
, a menos que seja o primeiro argumento 1.0
. Há mais problemas, nem todos abordados nos documentos .math.exp
sofre os mesmos problemas que math.pow
. Uma solução para corrigir isso para o estouro é usar código semelhante a este:
try:
res = math.exp(420000)
except OverflowError:
res = float('inf')
Nota 1: como uma advertência adicional, que, como definido pelo padrão IEEE, se o resultado do cálculo sub ou estouros, o resultado não será uma infinidade sub ou erro de excesso, mas positivo ou negativo: 1e308 * 10.0
os rendimentos inf
.
Nota 2: como qualquer cálculo com NaN
retornos NaN
e qualquer comparação com NaN
, inclusive NaN
ele próprio false
, você deve usar a math.isnan
função para determinar se um número é realmente NaN
.
Nota 3: embora o Python suporte a gravação float('-NaN')
, o sinal é ignorado, porque não existe sinal NaN
internamente. Se você dividir -inf / +inf
, o resultado será NaN
, não -NaN
(não existe).
Nota 4: tenha cuidado com qualquer uma das opções acima, pois o Python se baseia na biblioteca C ou Java para a qual foi compilado e nem todos os sistemas subjacentes implementam todo esse comportamento corretamente. Se você quiser ter certeza, teste o infinito antes de fazer seus cálculos.
Means) Significa recentemente desde a versão 3.2 .
²) Os pontos flutuantes suportam zero positivo e negativo, portanto: x / float('inf')
mantém seu sinal e -1 / float('inf')
produz -0.0
, 1 / float(-inf)
produz -0.0
, 1 / float('inf')
produz 0.0
e -1/ float(-inf)
produz 0.0
. Além disso, 0.0 == -0.0
étrue
, você tem que verificar manualmente o sinal se você não quer que ele seja verdadeiro.
-1 * float('infinity') == -inf
O mesmo acontece com C99 .
A representação de ponto flutuante IEEE 754 usada por todos os processadores modernos possui vários padrões de bits especiais reservados para infinito positivo (sinal = 0, exp = ~ 0, frac = 0), infinito negativo (sinal = 1, exp = ~ 0, frac = 0 ) e muitos NaN (não é um número: exp = ~ 0, frac 0).
Tudo o que você precisa se preocupar: alguma aritmética pode causar exceções / interceptações de ponto flutuante, mas essas não se limitam apenas a essas constantes "interessantes".
OverflowError
.
Eu encontrei uma ressalva que ninguém até agora mencionou. Não sei se isso ocorrerá frequentemente em situações práticas, mas aqui está por uma questão de perfeição.
Normalmente, o cálculo de um número infinito do módulo retorna como flutuador, mas uma fração do módulo infinito retorna nan
(não um número). Aqui está um exemplo:
>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction('1/3') % inf
nan
Arquivei um problema no rastreador de erros do Python. Pode ser visto em https://bugs.python.org/issue32968 .
Atualização: isso será corrigido no Python 3.8 .
UMA CAVEAT MUITO RUIM: Divisão por Zero
em uma 1/x
fração, até x = 1e-323
que seja, inf
mas quando x = 1e-324
ou pouco ele lançaZeroDivisionError
>>> 1/1e-323
inf
>>> 1/1e-324
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero
então seja cauteloso!
1e309
será interpretada como+inf
e-1e309
será interpretada como-inf
.