计算


13

函数具有靠近奇点X = 0。但是,可以提高奇点:对于x = 1,应该使f x = 1,因为 e x = k = 0 x kf:x(ex1)/xx=0x=1f(x)=1 因此 ex1/x=k=1x k 1

ex=k=0xkk!
然而,形式ëX-1/X不仅在没有定义X=0,它也是在该点附近的数值不稳定; 为了在数值上评估非常小的x的fx,可以使用泰勒展开,即上述幂级数的截断。
(ex1)/x=k=1xk1k!
(ex1)/xx=0f(x)x

:函数是否有名称?换句话说,这是一个普遍的问题吗?f

:是否有人知道可以很好地处理这种情况的C / C ++库,即使用适当度数的Taylor展开式接近0,而其他表示形式则远离零?

Answers:


19

expm1ex1x=0


17

这是取消错误的实例。C标准库(从C99开始)包括一个名为的函数expm1,可以避免此问题。如果使用expm1(x) / x代替(exp(x) - 1.0) / x,则不会遇到此问题(请参见下图)。 <code> fabs(expm1(x)/ x-(exp(x)-1.0)/ x)</ code>

数值算法准确性和稳定性的 1.14.1节中详细讨论了这个特殊问题的细节和解决方案。在W. Kahan的论文的第19页中也解释了相同的解决方案,该论文的标题为浮点计算中舍入的无心评估有多无效?expm1在GNU C库中的实际实现与上面的参考文献中描述的方法不同,并且在源代码中详细记录


1
谢谢,这就是我所需要的!不幸的是,我只能接受一个答案...
匿名

当然!没问题:-)
Juan M. Bello-Rivas

3

要回答第一个问题,不,该函数没有名称(至少不是一个广为人知的名称)。

正如其他人提到的那样,计算函数的最佳方法是处理几种特殊情况。这是任何库将如何计算函数的方式。

  1. 情况0:x = 0,返回1。
  2. |x|<δ1+x/2δdouble2e-85e-4
  3. 否则:return expm1(x)/x

截断的泰勒级数可以使更多的事情变得更加复杂,并且有更多特殊情况,但这可能不值得。实际上,尚不清楚案例1是否需要单独处理,因为k20指出,取消是安全的。但是,单独处理它会使我对此更有信心。


2

我记得这个问题早在此站点上曾被问过,令人惊讶的答案是,您只需要将完全相等的特殊情况设为零即可。误差几乎抵消了零。我没有链接。

是的,这个答案是完全错误的。我不确定为什么这么多赞成,可能是因为它这么权威。我找到了我所想的链接。它是在这里的数学stackexchange上,而不是在scicomp stackexchange上。所述expm1-free误差抵消式在由JM答案给出并且使用u = exp(x)变换。


xdx(edx1)/dx(1+dx1)/dx1

1
dx1+dx=1

0

要回答第一个问题并为第二个问题提供(可能在数值上无效)方法,请注意,这是伯努利数生成函数的逆函数


这是一个有趣的联系,感谢您指出。不幸的是,我相信三倍的金额将使这笔费用过高。而且,尚不清楚立即在何处截断每个和以获得所需的精度。
匿名

@匿名:你是说三倍的总和?您不需要伯努利多项式,只需要伯努利数,就可以提前列出它们。但是,是的,它仍然不比泰勒系列更好。
Nikolaj-K

如果很明显,仅对于任何输入只需要一个固定的有限数,则可以提前计算它们。
匿名

@匿名者:是的,就像您提前列出泰勒系数一样。
Nikolaj-K
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.