Mam proste pytanie, które jest naprawdę trudne dla Google (oprócz kanonicznego Co każdy informatyk powinien wiedzieć o arytmetyki zmiennoprzecinkowej ).
Kiedy należy używać funkcji takich jak log1p
lub expm1
należy używać zamiast log
i exp
? Kiedy nie należy ich używać? Czym różnią się różne implementacje tych funkcji pod względem ich wykorzystania?
floating-point
Tim
źródło
źródło
log1p
mówisz (szczególnie, jak to jest zaimplementowane, więc nie musimy zgadywać).Odpowiedzi:
Wszyscy wiemy, żeexp(x)=∑n=0∞xnn!=1+x+12x2+…
oznacza, że dla|x|≪1 , mamyexp(x)≈1+x . Oznacza to, że jeśli musimy oceniać w zmiennoprzecinkowymexp(x)−1 , dla|x|≪1 może wystąpić katastrofalne anulowanie.
Można to łatwo zademonstrować w Pythonie:
Dokładne wartościexp(10−8)−1exp(10−22)−1=0.000000010000000050000000166666667083333334166666668…=0.000000000000000000000100000000000000000000005000000…
Zasadniczo „dokładna” implementacja
exp
iexpm1
powinna być poprawna do nie więcej niż 1ULP (tj. Jedna jednostka ostatniego miejsca). Ponieważ jednak osiągnięcie tej dokładności powoduje powstanie „wolnego” kodu, czasami dostępna jest szybka, mniej dokładna implementacja. Na przykład w CUDA mamyexpf
iexpm1f
, gdzief
oznacza szybko. Według przewodnika programowania CUDA C, aplikacja. Dexpf
ma błędu 2ULP.Jeśli nie przejmujesz się błędami w kolejności kilku ULPS, zwykle różne implementacje funkcji wykładniczej są równoważne, ale uważaj, że błędy mogą być gdzieś ukryte ... (Pamiętasz błąd Pentium FDIV ?)
Jest więc całkiem jasne, żeexp(x)−1 dla małego x . Używanie go do ogólnego x nie jest szkodliwe, ponieważ
expm1
należy użyć do obliczeniaexpm1
oczekuje się, że będzie dokładny w całym zakresie:(W powyższym przykładzie1 jest znacznie poniżej 1ULP exp(200) , więc wszystkie trzy wyrażenia zwracają dokładnie tę samą liczbę zmiennoprzecinkową.)
Podobna dyskusja dotyczy funkcji odwrotnychlog(1+x)≈x dla |x|≪1 .
log
ilog1p
ponieważźródło
expm1(x)
zamiastexp(x)-1
. Oczywiścieexp(x) == exp(x) - 1
nie ma to miejsca.expm1(x)
powinna być dokładna do 1ULP w całym zakresie , stopniowo traci precyzję od kilku ULP, gdy x ≈ 1, do pełnego rozkładu, gdy x < ϵ , gdzie ϵ jest epsilonem maszynowym.exp(x) - 1
Aby rozwinąć różnicę między
log
ilog1p
, może być pomocne przywołanie wykresu, jeśli logarytm:log
log1p
log
log1p
źródło