在Javascript中,我无法弄清楚为什么230/100*100
会返回229.99999999999997
,而240/100*100
会返回240.
这也适用于460, 920
等......
有没有解决方案?
答案 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.25
为10.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也不会被舍入,而是被截断。