使用logarthms来避免数值下溢的算术问题

时间:2010-02-18 10:17:53

标签: logarithm numerical-methods

我有两个分数列表;

A = [ 1/212, 5/212, 3/212, ... ]

B = [ 4/143, 7/143, 2/143, ... ]

如果我们定义A' = a[0] * a[1] * a[2] * ...B' = b[0] * b[1] * b[2] * ...

我想计算A' / B'

的值

我的麻烦是A是B都很长并且每个值都很小所以计算产品会导致数值下溢很快...

我理解通过对数将产品转化为总和可以帮助我确定A'或B'中哪一个更大

max( log(a[0])+log(a[1])+..., log(b[0])+log(b[1])+... )

但我需要实际的比例......

我最好的选择是将数字表示保持为分数,即A = [ [1,212], [5,212], [3,212], ... ]并实现我自己的算术,但它变得笨拙而且我感觉有一种(简单的)对数方式我只是缺少....

A和B的分子不是来自序列。对于这个问题,它们也可能是随机的。如果它对A中所有值的分母有所帮助,那么B的所有分母都是如此。

欢迎任何想法!

3 个答案:

答案 0 :(得分:4)

您可以按稍微不同的顺序计算它:

A' / B' = a[0] / b[0] * a[1] / b[1] * a[2] / b[2] * ...

答案 1 :(得分:1)

如果你想把它保持在对数上,记住A / B对应于log A - log B,所以在你总结A和B的对数之后,你可以找到大于和小的对数。使用max(logsumA,logsumB)-min(logsumA,logsumB)对日志库进行取幂。

答案 2 :(得分:0)

去除分子和分母,因为它们对于整个序列是相同的。逐个元素地计算分子的比率(而不是@Mark建议),最后将结果乘以B的分母/分母的正确幂。

或者,如果在计算分母的分子或幂的乘积时,它会威胁整数溢出,如:

A'/B' = (numerator(A[0])/numerator(b[0]))*(denominator(B)/denominator(A) * ...

我可能会把一些分数颠倒过来,但我猜你能搞清楚吗?