javascript - 除法结果不正确

标签 javascript math bigdecimal division

我有一个时间计算器,多年来一直运行良好。但是,一直困扰我的一件事是,如果使用小数秒,结果将成为浮点“错误”的牺牲品。所以,我最近改用了 this BigDecimal library .

现在,我遇到了数学错误。这是我今天收到的错误报告中的一个简化测试用例:27436/30418 返回 1 而不是预期的 0.9019659412190151

为了说明我的问题,这是 Chrome 中的 Javascript 控制台 session :

> 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() 方法没有产生我期望的结果。我需要做哪些不同的事情?

更新

这里有一些更多的细节,以回应评论。

首先,有几个人认为使用 BigDecimal 有点矫枉过正。可能是这样,但我认为在做出该决定之前需要更多细节。这个应用程序是 time calculator ,所以有几件事促使我转向 BigDecimal。首先,因为这是一个计算器,所以向用户显示正确答案很重要。如果用户输入 0.1 s + 0.2 s,他们期望答案是 0.3 s,而不是 Javascript 将显示给他们的答案(0.30000000000000004 ).

我真的不想将精度限制在我可以在 JS 中使用的范围之外,以便我可以使用整数,因为我不知道我的用户需要的最大精度。大多数人从不使用小数秒,我想,但从我收到的电子邮件来看,有些人使用。我目前在内部以秒为单位存储所有时间。

有人建议我将数字存储为精确的分数。不幸的是,我不知道那是什么意思。也许是因为我对数学了解不多。我的知识还不足以推出自己的数学图书馆;这就是我使用 BigDecimal 的原因。它已经存在很长时间了,所以我不敢说我​​的问题是由于 BigDecimal 中的一个错误。我怀疑这是我使用它的方式中的错误。

最后,我并不是特别喜欢 BigDecimal。我愿意接受其他建议,前提是我可以将它们用于我不足的数学技能。

最佳答案

我还没有在任何生产代码中使用过 BigDecimal,但发现这个问题很有趣,所以我尝试了一下。关于需要 MathContext 作为除法函数的参数,您是对的。根据您的示例,这是我所做的:

console.log(firstB.divide(secondB, new MathContext(100)).toString());

创建一个上下文,告诉 BigDecimal 在科学模式输出中使用 100 位数字:

0.9019659412190150568742192123085015451377473864159379314879347754618975606548754027220724570977710566

还有一些选项可以控制不同的输出模式 PLAINSCIENTIFICENGINEERING + 各种舍入模式。

jsfiddle 上的完整示例

更新: 默认输出格式是 SCIENTIFIC,而不是 PLAIN。示例 here

更新 2: 创建了一个微型性能测试 here ,看起来 BigDecimal 比原生 javascript 除法慢大约 10000 倍。

关于javascript - 除法结果不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8737489/

相关文章:

performance - 将数字拆分为总和组件

c - gcc9+ 模数优化背后的数学

java - 将 ".00"添加到 Java 中的整数 BigDecimal

javascript - Google Chrome console.log 乱序?

javascript - 未知插件 "transform-decorators-legacy"在windows中使用react storybook时报错

javascript - 如何在 MongoDB shell 中将文档数组更改为值数组?

javascript - 使用偏移 KineticJS HTML5 从舞台保存图像

c - 如何在 OpenGL 中使用函数生成曲线

java - 为什么在 Java 中进行交易之前要与 BigDecimal.ONE 比较余额?

jsf - JSF 页面上的 BigDecimal 算法