计算日志(exp(条款)的总和)当"术语"非常小

时间:2014-10-18 04:12:31

标签: math sum precision largenumber natural-logarithm

我想计算log(exp(A1)+ exp(A2)) 下面的公式

 log(exp(A1) + exp(A2) ) = log[exp(A1)(1 + exp(A2)/exp(A1))] = A1 + log(1+exp(A2-A1)) 
当A1和A2较大且数值为exp(A1)= Inf(或exp(A2)= Inf)时,

是有用的。 (此公式在此主题中讨论 - > How to calculate log(sum of terms) from its component log-terms)。当A1和A2的角色被替换时,该公式为真。

我对这个公式的关注是A1和A2非常小。例如,当A1和A2为:

 A1 <- -40000
 A2 <- -45000

然后log(exp(A1)+ exp(A2))的直接计算是:

 log(exp(A1) + exp(A2))
 [1] -Inf

使用上面的公式给出:

 A1 + log(1 + exp(A2-A1))
 [1] -40000

这是A1的值。 将上面的公式与A1和A2的翻转角色一起给出:

A2 + log(1 + exp(A1-A2))
[1] Inf

三个值中哪一个最接近log的真值(exp(A1)+ exp(A2))?是否存在计算log(exp(A1)+ exp(A2))的稳健方法,当A1,A2较小且A1,A2较大时,可以使用该方法。

提前谢谢

2 个答案:

答案 0 :(得分:1)

您应该使用更准确的东西来进行直接计算。

当[他们]很大时,它并不“有用”。当差异非常消极时,这很有用。

x接近0时,log(1+x)约为x。因此,如果A1>A2,我们可以采用您的第一个公式:

log(exp(A1) + exp(A2)) = A1 + log(1+exp(A2-A1))

并按A1 + exp(A2-A1)逼近(并且近似值会变得更好,因为A2-A1更负面)。自A2-A1=-5000以来,这足以使近似值足够。

无论如何,如果y离零点太远(无论哪种方式),exp(y)会(超过|)流动一个double并导致0或无穷大(这是一个双重的,对吗?什么语言你正在用吗?)。这解释了你的答案。但由于exp(A2-A1)=exp(-5000)接近于零,因此您的答案约为-40000+exp(-5000),与-40000无法区分,因此一个是正确的。

答案 1 :(得分:1)

在如此巨大的指数差异中,你可以做到最安全,没有任意精度

  • 选择了最大的指数,让它为Am = max(A1,A2)
  • 所以:log(exp(A1)+exp(A2)) -> log(exp(Am)) = Am
  • 这是你能得到的最接近这种情况的
  • 因此,在您的示例中,结果为-40000+delta
  • 其中delta是非常小的

如果您想使用第二个公式,那么所有分解为计算log(1+exp(A))

  • 如果A为正,那么结果远非真实的
  • 如果A为否定则会截断为log(1)=0,以便您获得与上面相同的结果

<强> [注释]

  • 您的指数差异为base^500
  • 单精度32位浮点数可以存储最多(+/-)2^(+/-128)
  • 的数字
  • 双精度64位浮点数可以存储最多(+/-)2^(+/-1024)
  • 的数字
  • 所以当你的基数是10或e时,这远远不够你所需要的
  • 如果你有四倍的精度应该足够但是当你再次开始改变exp差异时你会很快达到现在的相同点

[PS]如果你需要更高的精度而没有任意精度

  • 您可以尝试创建自己的数字类
  • 内部存储数字number=a^b
  • 其中a,b是花车
  • 但为此您需要编写所有基本功能
  • *,/很容易
  • +,-是一场噩梦,但即便如此,也可能会有一些方法/算法