【发布时间】:2012-02-02 23:33:22
【问题描述】:
我有一个多年来运行良好的时间计算器。但是,一直困扰我的一件事是,如果使用小数秒,结果将成为浮点“错误”的牺牲品。所以,我最近改用this BigDecimal library。
现在,我遇到了数学错误。这是我今天收到的错误报告中的简化测试用例:27436 / 30418 正在返回 1 而不是预期的 0.9019659412190151。
为了说明我的问题,这是 Chrome 中的 Javascript 控制台会话:
> first = 27436
27436
> second = 30418
30418
> first / second
0.9019659412190151 // expected result, but using JS numbers, not BigDecimals
> firstB = new BigDecimal(first.toString())
o
> secondB = new BigDecimal(second.toString())
o
> firstB / secondB
0.9019659412190151 // this is a JS number, not a BigDecimal, so it's susceptible to the problems associated with floating-point.
> firstB.divide(secondB)
o // BigDecimal object
> firstB.divide(secondB).toString()
"1" // huh? Why 1?
> firstB.divideInteger(secondB).toString()
"0"
如您所见,divide() 方法没有产生我期望的结果。我需要做些什么不同的事情?
更新
这里有一些更多的细节,以回应 cmets。
首先,有几个人认为使用 BigDecimal 太过分了。可能是这样,但我认为在做出决定之前需要更多细节。这个应用程序是time calculator,所以有几件事促使我切换到 BigDecimal。首先,因为这是一个计算器,所以向用户显示正确答案很重要。如果用户输入 0.1 s + 0.2 s,他们希望答案是 0.3 s,而不是 Javascript 将显示的答案 (0.30000000000000004)。
我真的不想将精度限制在我可以在 JS 中使用的范围之外,以便我可以使用整数,因为我不知道我的用户需要的最大精度。我认为大多数人从不使用小数秒,但从我收到的电子邮件来看,有些人会这样做。我目前在内部将所有时间存储为秒。
有人建议我将数字存储为精确分数。不幸的是,我不知道那是什么意思。也许是因为我对数学不太了解。我对自己的数学库知之甚少;这就是我使用 BigDecimal 的原因。它已经存在了很长时间,所以我不敢说我的问题是由于 BigDecimal 中的一个错误。我怀疑这是我使用它的方式中的一个错误。
最后,我并没有特别喜欢 BigDecimal。我愿意接受其他建议,前提是我可以将它们用于我缺乏的数学技能。
【问题讨论】:
-
可能与精度有关。就像,如果精度太小,它只会四舍五入到最接近的整数。此外,仅仅因为浮点错误而使用 BigDecimal 似乎有点矫枉过正。您也可以将数字存储为精确的分数。
-
是的,使用 BigDecimal 对我来说也有点矫枉过正。尤其是如果您要对 time 等固定精度的东西进行计算,为什么不只使用整数(秒?毫秒?..?)然后进行所有适当的转换..?跨度>
-
0.1 对于舍入误差来说是一个相当大的差异,问题仍然存在于萤火虫中。您可能想提交错误报告。
-
@j08691:您能否解释一下为什么发布该链接以及它对我的情况有何帮助?正如我在帖子中解释的那样,我已经知道浮点错误的原因。我正在为我的特定问题寻找解决方案,但我看不到您的链接如何解决我的问题。
标签: javascript math bigdecimal division