10

可能的重复:
JavaScript 的数学被破坏了吗?

在 Javascript 中,我无法弄清楚为什么230/100*100返回229.99999999999997,而240/100*100返回240.

这也适用于460, 920等等......

有什么解决办法吗?

4

5 回答 5

9

问题:

230/100*100

= (230 / 100) * 100
= 2.3 * 100 in binary

二进制中的2.3是循环十进制:10.01001100110011001100110011001100...

由于精度有限,这个循环小数无法准确表示,我们得到类似2.29999999981373548507....


有趣的是,如果您选择这样的除法运算,使其可以用二进制准确表示(不是循环小数,所有数字都在 FP 标准所容纳的最大有效数字内),您将不会看到任何此类差异。

例如225/100*100=225

2.25二进制是10.01

测试转换:二进制到/从十进制


处理它:

检查浮点值之间的相等性时,请始终注意精度。向上/向下舍入到一定数量的有效数字是一种很好的做法。

于 2012-11-06T09:43:06.880 回答
8

在 JavaScript 中,所有数值都存储为IEEE 754 64 位浮点值(double在许多语言中也称为)。这种表示只有有限的精度(因此并非所有数字都可以准确表示)并且它是二进制的,因此看起来很容易用十进制表示的值可能会变得难以处理。

没有适合所有人的即用即弃的解决方案。如果您需要一个整数,那么只需使用Math.round.

于 2012-11-06T09:40:58.547 回答
1

此问题与浮点不准确性有关。有关更多详细信息,请参阅此问题: 浮点数学是否损坏?

于 2012-11-06T09:42:20.990 回答
1

出于同样的原因,如果你被迫保持一定的精度,并采取每一步,你会给出10/3*3as 9.99999...

假设您必须保持的精度是 10 位数。在10/3你有3.333333333. 然后,当您将其乘以 3 时,您将拥有9.999999999.

现在,既然我们知道 3 会永远持续下去,我们知道 9 会永远持续下去,所以我们知道答案真的是 10。但这不是这里的交易,交易是你尽可能地应用每一步可以,然后继续下一个。

除了会导致重复表示的数字外,可能还有一些可以精确表示的数字,但不能用您使用的位数表示。

正如10/3十进制230/100不能完美表示一样,二进制也不能完美表示。

于 2012-11-06T09:56:51.087 回答
0

JavaScript 中的除法不是整数除法,而是浮点数。

2.3 或 2.4 不能用浮点数精确表示。不同之处在于 2.4 最接近的 fp 是 2.4000000953,而 2.3 大约是 2.2999999523。

一个可以使用Math.round(x)或一个可以使用 JavaScript 技巧:

(x|0) 将 x 转换为整数,如 '|' 运算符将操作数强制为整数。即使在这种情况下,299.9943 也不是四舍五入而是截断。

于 2012-11-06T09:43:54.867 回答