我有一个时间计算器,多年来一直运行良好。然而,一直困扰我的一件事是,如果使用小数秒,结果将成为浮点“错误”的牺牲品。所以,我最近改用这个 BigDecimal 库 https://github.com/dtrebbien/BigDecimal.js.
现在,我遇到了数学错误。这是我今天收到的错误报告中的一个简化测试用例: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()
方法没有产生我期望的结果。我需要做哪些不同的事情?
Update
以下是针对评论的更多详细信息。
首先,一些人认为使用 BigDecimal 太过分了。可能是这样,但我认为在做出决定之前需要更多细节。这个应用程序是一个时间计算器 http://www.scottseverance.us/html/time_calculator.htm,所以有几件事促使我切换到 BigDecimal。首先,因为这是一个计算器,所以向用户显示正确的答案很重要。如果用户输入0.1 s + 0.2 s
,他们期望答案是0.3 s
,而不是 Javascript 将向他们显示的答案(0.30000000000000004
).
我真的不想将精度限制在 JS 中可以使用的范围之外,以便我可以使用整数,因为我不知道用户需要的最大精度。我认为大多数人从不使用小数秒,但从我收到的电子邮件来看,有些人会这样做。我目前在内部将所有时间存储为秒。
有人建议我将数字存储为精确分数。不幸的是,我不知道这意味着什么。也许是因为我对数学了解不多。我的知识还不足以建立我自己的数学库;这就是我使用 BigDecimal 的原因。它已经存在很长时间了,所以我很犹豫是否说我的问题是由于 BigDecimal 中的错误造成的。我怀疑这是我使用它的方式中的一个错误。
最后,我并不是特别热衷于 BigDecimal。我愿意接受其他建议,只要我可以用我缺乏的数学技能来使用它们。