Python Infinito - quaisquer advertências?
Pergunta
Assim, Python tem infinito positivo e negativo:
float("inf"), float("-inf")
Isso só parece ser o tipo de recurso que tem que ter alguma ressalva. Existe algo que eu deveria estar ciente de?
Solução
Você ainda pode obter valores não-um-número (NaN) de aritmética simples inf
envolvendo:
>>> 0 * float("inf")
nan
Observe que você normalmente não obter um valor inf
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 valor inf
é considerado um valor muito especial com a semântica incomuns, por isso é melhor saber sobre uma OverflowError
imediatamente através de uma exceção, em vez de ter um valor de inf
silenciosamente injetado em seus cálculos.
Outras dicas
do Python segue o IEEE-754 padrão muito bem, que você pode usar como uma orientação, mas depende do sistema subjacente ele foi compilado, por isso < a href = "http://www.python.org/dev/peps/pep-0754/" rel = "noreferrer"> diferenças de plataforma podem ocorrer. Recently¹, a correção foi aplicada que permite "infinito", bem como "inf" , mas isso é de menor importância aqui.
As seções a seguir igualmente bem se aplica a qualquer linguagem que implementa IEEE aritmética de ponto flutuante corretamente, ele não é específico para apenas Python.
Comparação de desigualdade
Ao lidar com o infinito e maior que >
ou menos do que os operadores <
, os seguintes aspectos:
- qualquer número incluindo
+inf
é maior do que-inf
- qualquer número incluindo
-inf
é inferior+inf
- +inf é href="http://compilers.iecc.com/comparch/article/98-07-134" rel="noreferrer"> nem maior nem menor do que
+inf
-
-inf
não é nem maior nem menor do que-inf
- qualquer comparação envolvendo
NaN
é falso (inf
não é nem maior, nem menor do queNaN
)
Comparação por igualdade
Quando comparado por igualdade, +inf
e +inf
são iguais, como são -inf
e -inf
. Esta é uma questão muito debatida e pode soar controverso para você, mas é no padrão IEEE e Python se comporta assim.
Claro, +inf
é desigual a -inf
e tudo, incluindo a própria NaN
, é desigual a NaN
.
Cálculos com o infinito
A maioria dos cálculos com o infinito vai render o infinito, a menos que ambos os operandos são infinito, quando a divisão de operação ou modulo, ou com a multiplicação com zero, existem algumas regras especiais para manter em mente:
- quando multiplicado por zero, para o qual o resultado é indefinido, ele produz
NaN
- quando dividindo qualquer número (excepto em si infinito) por infinito, o que produz
0.0
ou-0.0
² . - quando dividindo (incluindo modulo) infinito positivo ou negativo pelo infinito positivo ou negativo, o resultado é indefinido, de modo
NaN
. - quando subtraindo, os resultados podem ser surpreendentes, mas siga matemática do senso comum :
- ao fazer
inf - inf
, o resultado é indefinido:NaN
; - ao fazer
inf - -inf
, o resultado éinf
; - ao fazer
-inf - inf
, o resultado é-inf
; - ao fazer
-inf - -inf
, o resultado é indefinido:.NaN
- ao fazer
- quando a adição, pode ser semelhante surpreendendo também:
- ao fazer
inf + inf
, o resultado éinf
; - ao fazer
inf + -inf
, o resultado é indefinido:NaN
; - ao fazer
-inf + inf
, o resultado é indefinido:NaN
; - ao fazer
-inf + -inf
, o resultado é-inf
.
- ao fazer
- usando
math.pow
,pow
ou**
é complicado, uma vez que 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 uma precisão de flutuação dupla (ele deve retornar infinity), mas quando a entrada éinf
ou-inf
, comporta-se correctamente e retornos querinf
ou0.0
. Quando o segundo argumento éNaN
, ele retornaNaN
, a menos que o primeiro argumento é1.0
. Há mais problemas, nem todos coberta nos docs . -
math.exp
sofre as mesmas questões quemath.pow
. A solução para corrigir isso para transbordamento é usar código semelhante a este:try: res = math.exp(420000) except OverflowError: res = float('inf')
Notas
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á um erro sub ou estouro, mas positiva ou infinito negativo:. yields 1e308 * 10.0
inf
Nota 2: , porque qualquer cálculo com NaN
retornos NaN
e qualquer comparação com NaN
, incluindo a própria NaN
é false
, você deve usar o math.isnan
função para determinar se um número é de fato NaN
.
Nota 3: que Python suporta escrita float('-NaN')
, o sinal é ignorado, porque não existe nenhum sinal na NaN
internamente. Se você dividir -inf / +inf
, o resultado é NaN
, não -NaN
(não existe tal coisa).
Nota 4: ter o cuidado de confiar em qualquer um dos acima, como Python depende da biblioteca C ou Java foi compilado para e nem todos subjacente sistemas de implementar todo esse comportamento corretamente. Se você quiser ter certeza, teste para o infinito antes de fazer seus cálculos.
¹) Recentemente meio desde versão 3.2 .
²) pontos flutuantes apoiar positivo e negativo zero, assim: x / float('inf')
mantém seu sinal e -1 / float('inf')
rendimentos -0.0
, os rendimentos 1 / float(-inf)
-0.0
, os rendimentos 1 / float('inf')
0.0
e rendimentos -1/ float(-inf)
0.0
. Além disso, 0.0 == -0.0
é true
, você tem que verificar manualmente o sinal, se você não quer que seja verdade.
O mesmo acontece com C99 .
A representação de ponto flutuante IEEE 754 utilizado por todos os processadores modernos tem vários padrões de bits especial reservado para o infinito positivo (sinal = 0, exp = ~ 0, frac = 0), infinito negativo (sinal = 1, exp = ~ 0, frac = 0), e muitos NaN (Not a Number:. exp = ~ 0, frac ? 0)
Tudo que você precisa se preocupar: um pouco de aritmética pode causar flutuante exceções de ponto / armadilhas, mas aqueles não estão limitados a apenas essas constantes "interessantes"
.Eu encontrei uma ressalva de que ninguém até agora tem mencionado. Eu não sei se ele vai vir para cima, muitas vezes em situações práticas, mas aqui é para o bem da integralidade.
Normalmente, o cálculo de um infinito número de módulo retorna a si mesmo um float, mas uma fração modulo infinito retornos 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
Eu arquivei um problema no rastreador de bug do Python. Pode ser visto em https://bugs.python.org/issue32968 .
Update: este será fixo em Python 3.8
.