np.exp() 的数值问题

Numerical issue with np.exp()

我有以下代码

x = -10
for i in range(2,10):
    print i, " | ",np.exp(-x**i)

具有以下输出:

2  |  3.72007597602e-44
3  |  inf
4  |  0.0
5  |  inf
6  |  0.0
7  |  inf
8  |  0.0
9  |  inf

为什么 i 的结果是 ~0 偶数,而 i 的结果是 Inf 奇数?

双精度浮点值(numpy 用于浮点运算)的最大值略低于 1.8e308 (1.8 * 10^308)。

table 中 3 的值将是 e^1000,WolframAlpha 说它比 2e434 小一点。问题是您要使用的数字太大,numpy 无法处理,因此对于奇数,您会得到无穷大。

偶数则反之;您计算的数字太小以至于 numpy 必须将其视为有效的零。

简答

因为 xi 如果 x < 0 则大于零=]i 为偶数且小于零,如果 i 为奇数。由于指数函数会生成非常大或非常小的数字以及非常大的正输入和非常大的负输入,因此这些值会四舍五入为无穷大或零,这对于 IEEE-754 数字来说是正常的。

对于奇数

默认情况下 Python handles floating point 数字为 IEEE-754 "double precision"。

double 的限制在 -1.7*10308 和 1.7*10308 之间,上面和下面的所有内容都被认为是是 -Inf+Inf。现在,如果您计算 i=3,您将得到:

exp(-(-10**3))=exp(-(-1000))=exp(1000)

或大约1.9*10434,明显高于阈值。对于每个奇数 i-10**i 的结果为负,因此 exp 的操作数为正,您将得到高于阈值的值。

对于偶数

对于偶数,结果为:

exp(-(-10**4))=exp(-10000)

这又是大约 1.13*10-4343

a double 可以表示的最小正值(大于零)是 2-53。得到的值明显偏低,所有正值都低于这个epsilon;四舍五入为零,仅仅是因为它是最接近的可表示值。

由于 x = -10x**i 将在正高值和负高值之间交替,-(x**i) 也是如此,这就是您编写 -x**i 时计算的值。np.exp(inf) = infnp.exp(-inf) = 0 所以对于足够大的数字,你在无穷大和 0 之间交替。

您可能想写成np.exp((-x)**i),这将使幂指数始终为正。