【问题标题】:Problem with arithmetic using logarithms to avoid numerical underflow (take 2)使用对数避免数值下溢的算术问题(取 2)
【发布时间】:2011-01-18 14:56:34
【问题描述】:

我有两个分数列表;

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' / (A'+B')B' / (A'+B')的值

我的问题是 A 和 B 都很长,每个值都很小,所以计算乘积会很快导致数值下溢......

我知道通过对数将乘积转化为和可以帮助我确定 A' 或 B' 中哪个更大

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

使用日志我可以计算出A' / B' 的值,但我该怎么做A' / A'+B'

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

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

欢迎提出任何想法!

( ps。我在 24 小时前询问了 similar question 关于比率 A'/B' 的问题,但实际上是 错误 的问题。我实际上是在 A'/(A'+B') 之后。对不起,我的错误。)

【问题讨论】:

  • 对不起,这是否意味着 A'/(A'+B') 和 B'/(A'+B')?是否缺少括号?
  • 是的,谢谢,我已经更正了。

标签: logarithm numerical-methods


【解决方案1】:

我在这里看到了几种方法

首先你会注意到

A' / (A'+B') = 1 / (1 + B'/A')

你知道如何用对数计算B'/A'

另一种方法是实现你自己的有理算术,但你不需要走得太远。由于您知道整个数组的分母相同,因此它会立即为您提供

numerator(A') = numerator(a[0]) * numerator(a[1]) ...
denumerator(A') = denumerator(a[0]) ^ A.length

您现在需要做的就是将 A' 和 B' 相加,这很容易,然后将 A'1/(A'+B') 相乘,这也很容易。这里最难的部分是标准化结果值,这是通过模运算完成的,而且很简单。

另外,由于您很可能使用一些流行的脚本语言,它们中的大多数都内置了有理算术类,Python 和 Ruby 肯定有。

【讨论】:

  • Python 3.x 有一个内置的 bigint。 int 是 bigint。这有助于保持高精度。
  • @Hamish,他实际上可能使用double 作为枚举数。他有下溢问题,我认为他不想进行超精确的计算,只要足够精确即可。
  • 嗯......当您将一个小数除以另一个时,您可能希望两者都保持良好的精度。
  • A' / (A'+B') = 1 / (1 + B'/A') 之类的东西是我想要的,谢谢!这是一个更大的部分的一部分,所以我热衷于尽可能地保持对数以节省更大的重写。干杯!
  • (虽然我是用 ruby​​ 编写的,但它是 hadoop pig 的原型,所以我试图尽可能地忽略 Rational)
【解决方案2】:

迄今为止我最好的选择是将数字表示形式保留为分数并实现我自己的算术,但它变得笨拙

您使用什么语言?如果您可以重载运算符,则应该很容易组成一个 Fraction 类,您几乎可以在任何地方将其视为一个数字。

例如,判断一个分数A / B是否大于C / D基本上是比较A * D是否大于B * C

【讨论】:

    【解决方案3】:

    A 和 B 在您提到的每个分数中都有相同的分母。列表中的每个术语都是这样吗?如果是这样,为什么在计算产品时不将其考虑在内?当 X 是值,n 是列表中的项数时,分母就是 X^n。

    如果你这样做,你会遇到相反的问题:分子溢出。您知道它不能小于 max(X)^n,其中 max(X) 是分子中的最大值,n 是列表中的项数。如果你能计算出来,你可以看看你的电脑是否会出现问题。你不能把 10 磅的东西放在一个 5 磅的袋子里。

    不幸的是,对数的性质将您限制为以下简化:


    (来源:equationsheet.com


    (来源:equationsheet.com

    所以你被困住了:


    (来源:equationsheet.com

    如果您使用的语言支持无限精度数字(例如 Java BigDecimal),它可能会让您的生活更轻松一些。但是在计算之前进行一些思考仍然是一个很好的论据。既然可以优雅,为什么还要使用蛮力?

    【讨论】:

      【解决方案4】:

      嗯...如果您知道A'(A'+B'),那么B'(A'+B') 应该是减去那个。我个人不会使用对数。我会使用实际的分数。我还会使用某种 BigInt 类来表示分子和分母。您使用哪种语言? Python 很适合。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-25
        • 1970-01-01
        • 2021-01-12
        • 1970-01-01
        相关资源
        最近更新 更多