常识指南
柔彩主题三 · 更轻盈的阅读体验

浮点比较相等技巧:为什么0.1 + 0.2不等于0.3?

发布时间:2025-12-15 18:50:29 阅读:369 次

在写网页表单验证或者做价格计算时,你可能遇到过这种奇怪的情况:JavaScript 里 0.1 + 0.2 === 0.3 居然返回 false。这并不是程序出错,而是浮点数精度问题带来的常见陷阱。

浮点数的存储原理

计算机用二进制表示数字,但像 0.1 这样的十进制小数,在二进制中是无限循环的(就像 1/3 在十进制中是 0.333…),所以只能近似存储。这就导致了微小的舍入误差。

比如在 JavaScript 中执行:

console.log(0.1 + 0.2); // 输出:0.30000000000000004

这个结果和 0.3 看起来几乎一样,但严格相等比较会失败。

别用 == 或 === 直接比较浮点数

直接使用全等或相等判断两个浮点数是否“相同”,很容易翻车。比如在电商网站计算总价时,用户看到的价格是 0.3 元,但系统算出来是 0.30000000000000004,若直接比对就会误判为不一致。

正确做法是引入一个“误差范围”,也就是常说的“容差”(epsilon)。

使用容差进行安全比较

我们可以定义一个很小的值,比如 Number.EPSILON,它表示 JavaScript 中可表示的最小差异。然后判断两个数的差是否在这个范围内:

function floatEqual(a, b) {
    return Math.abs(a - b) < Number.EPSILON;
}

floatEqual(0.1 + 0.2, 0.3); // true

不过注意,Number.EPSILON 只适用于接近 1 的数值范围。当处理更大或更小的数时,误差范围也需要相应调整。

按需设定相对误差

对于较大的数值,建议使用相对误差判断:

function approxEqual(a, b, tolerance = 1e-10) {
    const diff = Math.abs(a - b);
    const max = Math.max(Math.abs(a), Math.abs(b));
    return diff <= tolerance * max;
}

approxEqual(0.1 + 0.2, 0.3); // true
approxEqual(1000000.1 + 1000000.2, 2000000.3); // 依然可靠

这种方式能适应不同数量级的数值,避免因尺度变化导致判断失效。

实际应用场景

比如你在做一个前端计算器,用户输入 0.1 + 0.2,期望看到等于 0.3 的提示。如果不加容差处理,后台返回的结果哪怕只差亿分之一,也会让“结果正确”的判断失败。

又比如地图应用中判断两个坐标点是否重合,经纬度常以浮点数存储,直接比较可能漏判。加入容差后,就能合理识别“视觉上重合”的点。

其他语言也需注意

这个问题不限于 JavaScript。Python、Java、C++ 等语言都面临同样的浮点精度挑战。例如 Python 中也有:

print(0.1 + 0.2 == 0.3)  # False

解决思路类似:避免直接相等判断,改用区间或专用函数。Python 的 math.isclose() 就是为此设计的。

小技巧:转整数避坑

在金额计算这类场景中,一个简单粗暴但有效的办法是统一用“分”代替“元”。比如 0.1 元存成 10 分,全程用整数运算,最后再格式化显示。这样彻底绕开浮点数问题。

比如:

const total = 10 + 20; // 代表 0.1元 + 0.2元
const display = (total / 100).toFixed(2); // '0.30'

虽然损失了一点语义清晰性,但在关键业务中非常实用。