JavaScript中Math.round()处理不同精度小数结果不一致原因
为什么JavaScript中Math.round()对不同精度小数返回不一致的运算结果?
核心原因是JavaScript的数字类型统一采用IEEE 754 双精度64位浮点数格式存储,该格式最多只能精确表示15~17位有效十进制数字,超过长度限制的数字在代码解析阶段就会发生精度丢失,和Math.round()本身的舍入逻辑无关。
你可以通过以下代码复现这个现象:
console.log(Math.round(-0.5000000000000001) === -1); // true,原示例此处比较值写为1属于笔误 console.log(Math.round(-0.50000000000000001) === 0); // true console.log(Math.round(0.4999999999999999) === 0); // true console.log(Math.round(0.49999999999999999) === 1); // true
实际测试得到的16位精度阈值,刚好和双精度浮点数的有效位数上限对齐:
- 当小数精度在16位及以下时,你写在代码里的数字字面量可以被精确存储,传入
Math.round()的实际值和书写值完全一致,舍入结果自然符合预期 - 当小数精度达到17位及以上时,数字字面量在解析阶段就会被舍入到离它最近的、双精度浮点数可以表示的值,实际参与运算的数已经不是你代码里写的原值,自然会返回和直觉不符的结果
对应到测试的几个case:
-0.5000000000000001是16位小数,可被精确存储,值确实小于-0.5,按Math.round“0.5阈值向正无穷方向舍入”的规则,最终返回-1-0.50000000000000001是17位小数,存储时被自动舍入为-0.5,按照规则-0.5会向正无穷方向舍入到0,因此返回00.4999999999999999是16位小数,可被精确存储,值确实小于0.5,因此返回00.49999999999999999是17位小数,存储时被自动舍入为0.5,按照规则0.5会向正无穷方向舍入到1,因此返回1
这个精度问题不是
Math.round()独有的,所有JS数字运算触发浮点数有效位数上限时都会出现类似现象,经典的0.1 + 0.2 !== 0.3问题也是完全相同的成因。
内容的提问来源于stack exchange,提问作者hossein1976
相关产品推荐
相关产品推荐

