为什么230/100 * 100不返回230?

时间:2012-11-06 09:34:53

标签: javascript parseint decimal

  

可能重复:
  Is JavaScript’s Math broken?

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

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

有没有解决方案?

5 个答案:

答案 0 :(得分:9)

问题:

230/100*100

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

2.3 二进制是重复的小数:10.01001100110011001100110011001100...

由于精度有限,无法准确表示此重复小数,我们得到类似2.29999999981373548507...的内容。


有趣的是,如果您选择的分割操作可以准确表示( 不是重复的小数,且所有数字都在FP标准所容纳的最大有效数字内 )在二进制文件中,你不会看到任何这种差异。

E.g。 225/100*100 = 225

二进制文件中的

2.2510.01

<强> Test Conversion: Binary to/from Decimal


处理它:

检查浮点值之间的相等性时,始终要小心。向上/向下舍入到一定数量的有效数字是很好的做法。

答案 1 :(得分:8)

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

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

答案 2 :(得分:1)

此问题与浮点不准确有关。有关详细信息,请参阅此问题: Is floating point math broken?

答案 3 :(得分:1)

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

说你必须保持的精确度是10位数。 10/3 3.333333333之后你有9.999999999。然后当你乘以3时,你会得到10/3

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

除了会导致重复表示的数字之外,还有可以精确表示的数字,但不包括您正在使用的数字位数。

正如230/100无法用十进制表示完美,因此{{1}}无法在二进制中完美呈现。

答案 4 :(得分:0)

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

2.3或2.4无法在浮点中精确表示。不同的是2.4最接近的fp是2.4000000953,而2.3是2.2999999523。

可以使用Math.round(x),也可以使用JavaScript技巧:

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