Eu tenho uma pergunta simples que é realmente difícil para o Google (além do artigo canônico O que todo cientista da computação deve saber sobre aritmética de ponto flutuante ).
Quando funções como log1p
ou expm1
devem ser usadas em vez de log
e exp
? Quando eles não devem ser usados? Como as diferentes implementações dessas funções diferem em termos de uso?
floating-point
Tim
fonte
fonte
log1p
você está se referindo (especialmente como ela é implementada, para que não tenhamos que adivinhar).Respostas:
Nós todos sabemos queexp( x ) = ∑n = 0∞xnn != 1 + x + 12x2+ …
implica que para| x | «1 , temosexp( x ) ≈ 1 + x . Isso significa que, se tivermos que avaliar no ponto flutuanteexp( x ) - 1 , para| x | «1 cancelamento catastrófico pode ocorrer.
Isso pode ser facilmente demonstrado em python:
Os valores exatos sãoexp( 10- 8) - 1exp( 10- 22) - 1= 0.000000010000000050000000166666667083333334166666668 …= 0.000000000000000000000100000000000000000000005000000 …
Em geral, uma implementação "precisa"
exp
eexpm1
deve estar correta para não mais que 1ULP (isto é, uma unidade do último local). No entanto, como atingir essa precisão resulta em código "lento", algumas vezes uma implementação rápida e menos precisa está disponível. Por exemplo, na CUDA, temosexpf
eexpm1f
, ondef
significa rápido. De acordo com o guia de programação CUDA C, app. D oexpf
tem um erro de 2ULP.Se você não se importa com erros da ordem de poucos ULPS, geralmente implementações diferentes da função exponencial são equivalentes, mas cuidado para que os erros possam estar ocultos em algum lugar ... (Lembra do bug do Pentium FDIV ?)
Portanto, é bem claro queexp( x ) - 1 para x pequeno . Usá-lo para o x geral não é prejudicial, pois
expm1
deve ser usado para calcularexpm1
é esperado que seja preciso em toda a sua gama:(No exemplo acima1 1 está bem abaixo de 1ULP de exp( 200 ) , portanto, todas as três expressões retornam exatamente o mesmo número de ponto flutuante.)
Uma discussão semelhante vale para as funções inversasregistro( 1 + x ) ≈ x para | x | «1 .
log
elog1p
desdefonte
expm1(x)
vez deexp(x)-1
. Claro queexp(x) == exp(x) - 1
não se aplica em geral.expm1(x)
deva ter precisão de 1ULP em todo o intervalo , perde progressivamente a precisão de poucos ULPs quando x ≈ 1 para uma quebra completa quando x < ϵ , onde ϵ é máquina-épsilon.exp(x) - 1
Para expandir a diferença entre
log
elog1p
pode ser útil recuperar o gráfico se o logaritmo:log
log1p
log
log1p
fonte