JavaScript中字符串数值相乘出现精度差异的原因咨询
为什么
'2551.01' * 100会出现精度偏差,而'2551.02' * 100不会? 这其实是JavaScript(以及绝大多数现代编程语言)使用IEEE 754双精度浮点数来表示小数时的典型精度问题,咱们一步步拆解背后的原因:
IEEE 754的本质限制:
计算机用二进制存储数字,但很多十进制小数无法转换成精确的二进制小数——就像十进制里1/3是无限循环的0.333...一样,这些小数只能被近似存储。当你把字符串'2551.01'转换成数字时,JavaScript会将它转成一个最接近的IEEE 754双精度浮点数,这个值和真实的2551.01有极其微小的偏差。偏差被放大:
这个微小的偏差平时可能看不出来,但当你乘以100时,偏差也跟着被放大了。原本近似存储的2551.01实际值略大于真实值,乘以100后就变成了255101.00000000003,而不是精确的255101。为什么
2551.02没问题?
这纯属巧合:2551.02对应的近似浮点数,在乘以100之后,刚好能被IEEE 754双精度格式精确表示。换句话说,255102是一个可以用二进制精确存储的整数,而之前的近似值乘以100后刚好落在了这个精确值上,所以输出就是准确的255102。补充验证:
你甚至不需要用字符串,直接运行console.log(2551.01 * 100)也会得到同样的偏差结果,因为2551.01在代码里本身就是以近似浮点数的形式存在的。类似的经典例子还有console.log(0.1 + 0.2),输出是0.30000000000000004,也是同一个原理。
内容的提问来源于stack exchange,提问作者Leandro Alves




