我有一个简单的问题,对于Google来说真的很难(除了每位计算机科学家应该知道的有关浮点算术的规范论文之外)。
什么时候应该使用诸如log1p
或的功能expm1
代替log
和exp
?什么时候不应该使用它们?这些功能的不同实现在用法上有何不同?
我有一个简单的问题,对于Google来说真的很难(除了每位计算机科学家应该知道的有关浮点算术的规范论文之外)。
什么时候应该使用诸如log1p
或的功能expm1
代替log
和exp
?什么时候不应该使用它们?这些功能的不同实现在用法上有何不同?
Answers:
我们都知道,
这可以在python中轻松演示:
>>> from math import (exp, expm1)
>>> x = 1e-8
>>> exp(x) - 1
9.99999993922529e-09
>>> expm1(x)
1.0000000050000001e-08
>>> x = 1e-22
>>> exp(x) - 1
0.0
>>> expm1(x)
1e-22
精确值为
通常,“准确”的实现,exp
并且expm1
应正确不超过1ULP(即最后一个单元)。但是,由于达到此精度会导致代码“缓慢”,因此有时可以使用快速,精度较低的实现。例如在CUDA中,我们有expf
and expm1f
,其中f
代表快速。根据CUDA C编程指南,app。D的expf
错误为2ULP。
如果您不在乎几个ULPS顺序的错误,通常指数函数的不同实现是等效的,但是请注意,错误可能隐藏在某处...(还记得Pentium FDIV错误吗?)
所以这是很清楚,expm1
应该被用来计算为小型。将其用于一般并无害处,因为expm1
可以预期它在整个范围内都是准确的:
>>> exp(200)-1 == exp(200) == expm1(200)
True
(在上面的示例中远低于 1ULP ,因此所有三个表达式都返回完全相同的浮点数。)
类似的讨论适用于逆函数log
和log1p
自为。
expm1(x)
代替exp(x)-1
。当然exp(x) == exp(x) - 1
一般不成立。
为了扩大两者之间的差异,如果对数log
,log1p
则可能有助于调出图形:
log
is potentially a large negative number. For example and and so on. This can be useful, but it can also distort your data towards large negative numbers, especially if your dataset also contains numbers much larger than zero.
On the other hand, as approaches , the value of approaches from the positive direction. For example and . So log1p
produces only positive values and removes the 'danger' of large negative numbers. This generally insures a more homogeneous distribution when a dataset contains numbers close to zero.
In short, if the dataset is all greater than , then log
is usually fine. But, if the dataset has numbers between and , then log1p
is usually better.
log1p
你指的是(它尤其是如何实现的,所以我们不必去猜测)。