何时使用python函数expm1而不是exp-1

时间:2017-12-09 05:07:58

标签: python function numpy

expm1“函数避免了对小x直接评估exp(x)-1所涉及的精度损失。”

对于什么是小的,有经验法则吗? 1e-1,1e-10,1e-100? (方面问:是否存在不能始终使用expm1的性能或其他原因?)

np.info(np.expm1)
Examples
--------
The true value of ``exp(1e-10) - 1`` is ``1.00000000005e-10`` to
about 32 significant digits. This example shows the superiority of
expm1 in this case.

>>> np.expm1(1e-10)
1.00000000005e-10
>>> np.exp(1e-10) - 1
1.000000082740371e-10

1 个答案:

答案 0 :(得分:1)

简短回答

如果6个有效十进制数字足够你,exp(x)-1可以达到x为1e-10。通常,当x约为10**(-N)时,您将丢失N个十进制数字的精度。我们从大约16位双精度开始。

为什么不总是使用expm1?因为expm1(x) + 1绝对没有exp(x)的优势,所以无论x有多小。当您的计算实际需要expm1之类的东西时,使用exp(x) - 1才有意义。人们必须考虑更广泛的计算背景。

答案很长

它并不是关于x有多小,而是关于如何在计算中使用exp(x)。我应该在Loss of significance的更广泛背景下理解expm1的目的。某些公式在某些参数范围内会失去重要性;一个人必须分析公式,看看它是否以及何时发生。如果在某个范围内存在潜在的重要性损失,请将公式重新修改为代数相等但数值稳定的代数。维基百科在二次方程的例子中很好地解释了这一点。

如果您的目标是计算exp(x)3*exp(x) + 4等,则应使用exp。这里没有重要意义,无论将expm1置于这样的公式中都没有任何好处,无论x有多小。写expm1(x) + 1而不是exp(x)完全没有意义。

如果您的公式为exp(x) - 1exp(x) - cos(x),那么小x可能会失去重要性。这并不总是重写的理由;如果您只计划在x为1或更大时使用此公式,则没有问题。如果您可以使用绝对错误处于机器epsilon级别(1e-16左右),并且不关心相对错误,则没有问题。

当失去意义时,由信息的最终用户决定可以接受多少损失。通常,获得6位有效数字对于实际目的而言是足够的,因此从双精度精度中丢失10位小数可能是可接受的。在这种情况下,当exp(x) - 1小于x时,公式1e-10会导致不可接受的精度损失。实际上,exp(x) - 1的值接近x,但exp(x)看起来像1.00000000 ...在点为0后有10位数;所以x本身只剩下6位数字。

以数字更安全的形式重写函数需要一些人力,才能计算出所需的代数或三角函数。这种重写的例子:

f = lambda x: np.exp(x) - np.cos(x)
g = lambda x: np.sqrt(x**2 + 1) - 1  

上述数字更安全的形式:

f_safe = lambda x: np.expm1(x) + 2*np.sin(x/2)**2 
g_safe = lambda x: x / (np.sqrt(x**2 + 1) + 1)

np.exp(x) - np.cos(x)重写为np.expmp(x) - np.cos(x) + 1根本没有任何好处;我们必须考虑整个计算,以消除几乎相等的数字的减法。