J'ai une question simple qui est vraiment difficile pour Google (à part le canonique que tout informaticien devrait savoir sur le papier arithmétique à virgule flottante ).
Quand faut log1p
- expm1
il utiliser des fonctions telles que ou au lieu de log
et exp
? Quand ne devraient-ils pas être utilisés? Comment les différentes implémentations de ces fonctions diffèrent-elles en termes d'utilisation?
log1p
à quoi vous faites référence (en particulier comment il est mis en œuvre, donc nous n'avons pas à deviner).Réponses:
Nous savons tous queexp(x)=∑n=0∞xnn!=1+x+12x2+…
implique que pour|x|≪1 , on aexp(x)≈1+x . Cela signifie que si nous devons évaluer en virgule flottanteexp(x)−1 , pour|x|≪1 annulation catastrophique peut se produire.
Cela peut être facilement démontré en python:
Les valeurs exactes sontexp(10−8)−1exp(10−22)−1=0.000000010000000050000000166666667083333334166666668…=0.000000000000000000000100000000000000000000005000000…
En général, une mise en œuvre «précise» de
exp
etexpm1
devrait être correcte à pas plus de 1ULP (c'est-à-dire une unité de la dernière place). Cependant, étant donné que l'atteinte de cette précision entraîne un code "lent", une implémentation rapide et moins précise est parfois disponible. Par exemple, dans CUDA, nous avonsexpf
etexpm1f
, oùf
signifie rapide. Selon le guide de programmation CUDA C, app. D l'expf
a une erreur de 2ULP.Si vous ne vous souciez pas des erreurs de l'ordre de quelques ULPS, généralement différentes implémentations de la fonction exponentielle sont équivalentes, mais attention aux bogues qui peuvent être cachés quelque part ... (Rappelez-vous le bogue Pentium FDIV ?)
Il est donc assez clair que celaexp(x)−1 pour les petits x . Son utilisation pour le x général n'est pas nocive, car elle
expm1
devrait être utilisé pour calculerexpm1
devrait être précise sur toute sa plage:(Dans l'exemple ci-dessus1 est bien en dessous de 1ULP deexp(200) , donc les trois expressions renvoient exactement le même nombre à virgule flottante.)
Une discussion similaire vaut pour les fonctions inverseslog(1+x)≈x pour |x|≪1 .
log
etlog1p
puisquela source
expm1(x)
place deexp(x)-1
. Bien sûr,exp(x) == exp(x) - 1
ne tient pas en général.expm1(x)
devrait être précis à 1ULP sur toute la plage , il perd progressivement la précision de quelques ULP lorsque x ≈ 1 à une panne complète lorsque x < ϵ , où ϵ est epsilon machine.exp(x) - 1
Pour développer la différence entre
log
etlog1p
il peut être utile de rappeler le graphique si le logarithme:log
log1p
log
log1p
la source