对大数使用对数而不是除法?
Posted
技术标签:
【中文标题】对大数使用对数而不是除法?【英文标题】:Using logarithm instead of division for large numbers? 【发布时间】:2011-02-20 14:22:14 【问题描述】:我真的无法为我的问题想出一个合适的标题,但请允许我介绍一下我的情况;我想以以下形式计算显着性比率:p = 1 - X / Y
这里的X来自一个迭代过程;该过程需要大量的步骤,并计算该过程可以以多少种不同的方式结束在不同的状态(存储在 HashMap 中)。迭代结束后,我会选择一些状态并将它们的值相加。很难说这些数字有多大,所以我打算将总和实现为BigInteger
。
Y 来自一个以千为单位的数字的二项式系数。我倾向于使用 logGamma 来计算这些系数,从而得到该值的自然对数。
我感兴趣的是以最好/最有效的方式进行除法X / Y。如果我可以得到自然对数中的 X,那么我可以减去幂并将结果设为 1 - e ^ (lnX - lnY)。
我看到BigInteger
不能被Math.log
对数,在这种情况下我该怎么办?
【问题讨论】:
由于您将记录日志,因此结果不会完全精确,并且 BigInteger 的优势将丢失。那你能用双打代替吗? 【参考方案1】:您也许可以使用双打。 double 可以非常大,大约 1.7e308。它缺乏的是精度:它只支持大约 15 位数字。但是,如果您可以使用 15 位精度(换句话说,如果您不关心 1,000,000,000,000,000 和 1,000,000,000,000,001 之间的差异),那么双精度数可能会让您足够接近。
【讨论】:
很有趣,我不知道双打可以容纳这么大的数字,但我不得不问,当您不能真正使用前 15 位以外的任何其他数字时,保留 300 多个数字有什么意义?好吧,我的问题是,正如我在该部门中提到的更多,所以我想这不应该那么重要......我会试一试,看看会发生什么:) 澄清一下,我的意思是,使用 BigInteger 将所有内容相加,然后转换为 double 以生成日志。 关于你问的问题,我想简单的答案是,当你需要处理这么大的数字但不关心有超过 15 位的精度。 :-) 但是举一个真实的例子,以美分为单位的美国国债大约是 15 位数,您可以想象,如果您的工作涉及跟踪债务,您可能不会太在意十分之一或百分之一美分。 问题是双精度不是恒定的。遵循 IEEE-754 标准的 fp 数学的最大可能误差是 0.5 ULP(即可能的最佳结果 - 这在计算上非常复杂,因此快速数学库通常会增加该误差),但相对因子介于:0.5 * b^- p 啊,注意标准的 java 数学库只保证结果在 1-2 ulps 以内,如果精度很重要,StrictMath 将遵循 IEEE 标准。【参考方案2】:如果您要计算以千为单位的数字的二项式系数,那么Double
s 将不够好。
相反,我倾向于在数字上调用 toString 方法,并将日志计算为 log(10) * number.toString().length() + log(asFloat("0." + number.toString())
其中 asFloat 采用数字的字符串表示并将其转换为浮点数。
【讨论】:
我不确定我是否遵循,您能否详细说明,或者提供一个资源,让我可以阅读您的建议? 想象一下你有无限精确的数学。那么一个 n 位整数 N 总是可以改写为 (N/10^n)*10^n。第一个数字是 0.(N 的位数)形式的浮点数,这是我们可以合理准确地表示在 Float 内部然后取对数的东西,另一个对数是 10*log(10 )。这就是我的全部建议。【参考方案3】:如果您需要最大精度,如何将 BigIntegers 转换为 BigDecimals 并对其进行代数。如果精度不是最重要的,那么也许您可以将 BigIntegers 转换为双精度数并用它们做简单的代数。也许您可以告诉我们更多关于您的问题领域以及为什么您认为对数是最好的方法。
【讨论】:
你的意思是BigDecimal
s 上的除法?这样做的潜在问题是将二项式系数从对数值变为BigDecimal
或BigInteger
。感觉在对数刻度上工作会“更聪明”。我不确定您所说的问题域是什么意思,但是正如我在问题中提到的,我正在开发一种工具,该工具可以查找具有许多步骤的过程的可能结果,并计算比率。如果您想了解具体细节,我会尝试进一步澄清......以上是关于对大数使用对数而不是除法?的主要内容,如果未能解决你的问题,请参考以下文章