在写网页或者做前端开发的时候,你有没有遇到过这种奇怪的情况:明明是0.1加0.2,结果却不是0.3?
比如你在控制台敲下这行代码:
console.log(0.1 + 0.2); // 输出:0.30000000000000004
看到这个结果,很多人第一反应是:ref="/tag/137/" style="color:#B2A89E;font-weight:bold;">JavaScript是不是出bug了?其实不是语言的问题,而是浮点数在计算机底层的表示方式决定的。
浮点数是怎么存的?
计算机用的是二进制,而像0.1这样的十进制小数,在二进制里是无限循环的。就像1/3在十进制里是0.333…一样,0.1在二进制里也是个除不尽的数。
JavaScript使用IEEE 754标准的双精度浮点数格式来存储数字,这种格式只能精确表示有限位的二进制小数。当它试图把0.1转换成二进制时,只能取一个近似值,这就带来了误差。
不只是0.1 + 0.2
这个问题并不孤单。类似的计算都会出现细微偏差:
0.2 + 0.4; // 结果是 0.6000000000000001
0.1 + 0.7; // 结果是 0.7999999999999999
如果你在做价格计算、金融逻辑或者需要精确比较数值的地方直接用等号判断,可能就会踩坑。比如用户买了两件0.1元的商品,总价显示0.3元,但程序算出来是0.30000000000000004,再拿这个值去和数据库里的0.3比对,结果就不相等了。
怎么避免被坑?
最简单的办法是别直接用===比较浮点数。可以设置一个极小的误差范围,称为“机器精度”。
const EPSILON = 0.0000001;
function isEqual(a, b) {
return Math.abs(a - b) < EPSILON;
}
isEqual(0.1 + 0.2, 0.3); // true
另一种常见做法是把小数转成整数运算。比如金额统一用“分”来计算,最后再除以100显示成“元”。这样完全避开浮点数。
const total = (10 + 20) / 100; // 10分 + 20分 = 30分 → 0.3元
console.log(total); // 0.3
还有一些库专门处理这类问题,比如 decimal.js 或 big.js,适合在金融类项目中使用,能保证高精度运算。
别让小数毁了你的判断
下次再看到奇怪的浮点结果,先别急着骂JavaScript。这是几乎所有编程语言都会面对的问题,C、Java、Python也都一样。关键是要意识到它的存在,并在敏感场景做好防护。
尤其是在处理用户支付、库存扣减、数据校验这些地方,多一层考虑,少一个线上事故。