计算机是如何计算指数函数 $e^{x}$ 的呢?
本文并不是为了探究各种编程语言中数学计算函数库对 $e^x$ 函数的具体实现,而是提供一种计算思路,来帮助理解 $e^x$ 函数的计算原理,并使用 C 语言来实现这个算法。
计算原理
泰勒展开
函数 $\exp{(x)} = e^x$ 的图像如下所示:
与计算对数函数 $\log{x}$ 相似,指数函数的计算也是对 $x$ 进行处理后,使用泰勒公式进行展开计算。
指数函数 $e^x$ 的泰勒展开如下:
对 $e^x$ 进行展开也是有条件的,那便是要求 $x \rightarrow 0$ ,即以上的展开式只对 $x$ 在 0 点附近有效。
同时,展开式的精度和 $x$ 与 0 点的距离和展开的项数有关,如下:
以上是对 $e^x$ 分别进行两项、四项、六项展开的图像。各自的误差如下:
可以看出,在相同的展开项数下,$x$ 越靠近 0 点,误差越小;$x$ 固定时,展开项数越多,误差越小。
参数归约化
为了能够更加精确计算出更大范围的 $x$ 值的 $e^x$ 结果,首先要对原式进行处理。
我们知道,在计算机中,实数使用 IEEE 浮点数来表示,那么计算机其实更加善于计算 $2^x$,只要对浮点数的阶码进行处理就能计算得出 $2^x$ 的结果。
那么我们就要想办法,将以 $e$ 为底的指数函数 $e^x$ 转化为以 2 为底的指数函数 $2^x$的计算,至少要部分转化。
我们知道:
于是:
其中 $\log_2e \approx 1.442695$ 为常数,那么我们就成功地将计算 $e^x$ 的问题转换为计算 $2^{x\log_2e}$ 的问题了。
令 $t = x\log_2{e}$,则:
但是问题又来了,通过构造阶码的形式来计算 2 的次幂,只能计算 2 的整数次幂,而 $t$ 为实数,那该怎么办呢?
这时要利用指数函数的一个性质:
我们将 $t$ 分为整数部分 $m$ 与 小数部分 $n$,则:
对于整数次幂 $2^m$ 可通过构造阶码的形式来实现,对于小数次幂 $2^n$ ,则可对其进行再次转化为 $e^x$ 的形式,对其进行展开:
因为 $2 = e^{\ln2}$ ,所以:
因为 $n \in (-1,1),\ln2 \approx 0.693147$ ,所以 $n\ln2 \in (-0.693147, +0.693147)$ ,已经足够接近 0 点,所以可以对其使用泰勒展开进行计算。
令 $k = n\ln2,\quad k \in (-0.693147, +0.693147)$,则:
那么:
对于 $e^k$,根据 (1) 式:
实现思路
先将 $x$ 乘以 $\log_2{e} \approx 1.442695$ 得到 $t$:
1 | float x = 3.14; |
分别取得 $t$ 的整数部分 $m$ 和小数部分 $n$:
1 | m = (round)((int)(t * 2.0) / 2); |
通过 $m$ 来构造 $2^m$:
1 | m = (m + 127) << 23; |
然后将 $n$ 乘以 $\ln2$ 得到 $k$:
1 | float k = n * 0.693147; // 0.693147 = ln(2) |
再使用泰勒公式将其展开即可。
代码实现
源码
1 |
|