6

我有两个分数列表;

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' 中的哪个更大

IEmax( 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 小时前就该比率提出了类似的问题A'/B',但这实际上是一个错误的问题。我实际上是在追问A'/(A'+B')。对不起,我的错误。)

4

4 回答 4

5

我在这里看到了几种方法

首先你可以注意到

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 肯定有它们。

于 2010-02-19T02:56:35.680 回答
1

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

您使用什么语言?Fraction如果您可以重载运算符,那么构建一个几乎可以在任何地方都可以视为数字的类应该真的很容易。

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

于 2010-02-19T02:57:08.703 回答
1

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

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

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

替代文字
(来源:equationsheet.com

替代文字
(来源:equationsheet.com

所以你被困在:

替代文字
(来源:equationsheet.com

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

于 2010-02-19T02:59:09.590 回答
0

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

于 2010-02-19T03:01:03.780 回答