C++ exp()函数的浮点实现是否等效于截断泰勒级数展开?

C++ exp()函数的浮点实现是否等效于截断泰勒级数展开?,c++,cmath,exp,taylor-series,C++,Cmath,Exp,Taylor Series,cmath中exp()函数的浮点实现是否相当于非常高阶的截断泰勒级数展开?我们应该记住的一个可能的错误来源是,表示答案的位数是有限的,这取决于所使用的C库实现。在非常流行的glibc中,它不是。它取决于编译器、C运行时和处理器的实现。然而,无论谁计算指数,都不太可能使用泰勒展开,因为存在更好的方法 根据glibc的说法,它可能会使用自己的实现,该实现在注释中说明了这一点(来自sysdeps/ieee754/dbl-64/e_exp.c): 或者,它可以使用硬件支持的处理器指令进行浮点计算,如x8

cmath中exp()函数的浮点实现是否相当于非常高阶的截断泰勒级数展开?我们应该记住的一个可能的错误来源是,表示答案的位数是有限的,这取决于所使用的C库实现。在非常流行的glibc中,它不是。它取决于编译器、C运行时和处理器的实现。然而,无论谁计算指数,都不太可能使用泰勒展开,因为存在更好的方法

根据glibc的说法,它可能会使用自己的实现,该实现在注释中说明了这一点(来自sysdeps/ieee754/dbl-64/e_exp.c):

或者,它可以使用硬件支持的处理器指令进行浮点计算,如x86 FPU。在这两种情况下,您都可能得到一个精确的四舍五入值

cmath中exp()函数的浮点实现是否相当于非常高阶的截断泰勒级数展开

相当于?对这是因为任何适当的
exp()
实现都有大约半个ULP(最小精度单位)的错误。忽略有限精度算法的问题,我们总是可以构造一个截断的泰勒级数来做同样的事情


但是,
exp()
的任何适当实现都不会使用泰勒展开。这将是非常缓慢的,并且不会达到预期的精度。这将是一个彻头彻尾的愚蠢实现。更好的做法是利用2x和ex之间存在着很强的关系这一事实,并且考虑到浮点数的2表示几乎具有普适幂,2x的计算相当容易。

仅举一个如何计算exp(x)的示例:

如果x相当大,则结果为+inf。如果x相当小,则结果为0

设k=圆形(x/ln2)。然后exp(x)=2^k*exp(x-kln2)。2^k很容易计算。一个小问题是在没有任何舍入误差的情况下计算x-k ln2。这很简单:让L1=ln2四舍五入为35位,L2=ln2-L1。k是一个小整数,因此k*L1没有舍入误差,x-k*L1也没有舍入误差;然后我们减去k*L2,它很小,因此舍入误差很小

为了更快地完成这项工作(无需除法),我们计算k=四舍五入(x*(1/ln2))。我们检查x是否接近零,所以不需要整个计算。无论如何,我们现在计算exp(x),结果在sqrt(1/2)和sqrt(2)之间


可以使用泰勒多项式计算exp(x)。相反,您可能会使用切比雪夫多项式以更低的次数最小化截止误差。仔细一点,你可以找到一个多项式,它的截止误差大大小于结果的最低位

这是极不可能的。硬件运算单元(以及软件实现)有更好的“实用”算法,收敛速度更快。虽然泰勒级数在理论上是可行的,但在使用英特尔编译器时,级数展开可能会受到严重的精度损失。glibc中使用什么算法来计算exp()?@Tarek我不知道它到底是什么,一些涉及魔法常数的东西,但为什么不亲自看看呢?@Tarek:我也不知道,但比泰勒展开更好的方法是在有限区间上使用预先计算的常数,并利用浮点的指数格式,以便将问题减少到该有限区间。
/* An ultimate exp routine. Given an IEEE double machine number x          */
/* it computes the correctly rounded (to nearest) value of e^x             */