为什么JavaScript中直接赋值0.3正常,0.1+0.2运算却出现精度丢失?
浮点数精度疑问解答
首先看示例代码:
let a = 0.1; let b = 0.2; let c = 0.3; let d = a + b; console.log(c.toString()); //0.3 console.log(d.toString()); //0.30000000000000004
核心误区纠正
0.3确实无法被双精度浮点数精确表示,直接赋值的变量c也没有存储完全精确的0.3,你看到的toString输出差异是JS浮点数转字符串的规则导致的,和存储精度是否丢失没有关系。
具体原因说明
- 所有JS的数字默认都以64位双精度浮点数格式存储,十进制小数转成二进制存储时,如果无法用有限位二进制表示,就会做舍入,存储为和原始值最接近的可表示双精度值。0.1、0.2、0.3三个十进制小数都属于无法精确存储的类型,直接赋值时就已经做了舍入操作。
- 字面量
0.3转双精度后得到的是离真实十进制0.3最近的可表示值,我们记为v1;而0.1和0.2各自转成双精度舍入后相加,得到的结果是离真实十进制0.3第二近的可表示值,记为v2,二者的差值在1e-16量级,非常微小。 - JS内置的
Number.prototype.toString()方法有个明确的设计规则:输出能唯一区分当前双精度值和其他所有双精度值的最短十进制字符串。v1对应的最短字符串刚好就是"0.3",而v2无法用"0.3"作为唯一标识,否则会和v1混淆,因此就输出了更长的"0.30000000000000004"。
验证方法
你可以通过更高精度的输出确认两个值都不是精确的0.3:
console.log(c.toFixed(20)); // 输出:0.29999999999999998890 console.log(d.toFixed(20)); // 输出:0.30000000000000004441 console.log(c === d); // 输出:false
内容的提问来源于stack exchange,提问作者Hemant
相关产品推荐
相关产品推荐

