两个浮点数怎么精确比较?别再直接用==了

写代码时,经常会遇到要比较两个数字是否相等的情况。整数很简单,5 == 5 没问题。但换成浮点数,比如 0.1 + 0.2 == 0.3,结果居然是 false,这就让人一头雾水了。

这并不是程序出 bug,而是浮点数在计算机里的表示方式决定了它天生有精度误差。IEEE 754 标准下,像 0.1 这样的小数无法被二进制精确表示,就像十进制里 1/3 写不成有限小数一样。所以计算结果其实是近似值,直接用 == 比较自然会翻车。

别用 == 直接比浮点数

来看个例子:

let a = 0.1 + 0.2;
let b = 0.3;
console.log(a === b); // false

虽然我们觉得 a 和 b 应该相等,但实际 a 的值是 0.30000000000000004,和 0.3 差了一丁点。这种情况下,就得换思路了。

用“误差范围”来判断相等

既然浮点数有精度问题,那就别追求绝对相等,转而判断两个数是不是“足够接近”。这个“足够接近”的范围,叫作“容差”或“epsilon”。

常见的做法是定义一个很小的数,比如 1e-10,然后看两个浮点数的差的绝对值是否小于它:

function floatEqual(a, b, epsilon = 1e-10) {
return Math.abs(a - b) < epsilon;
}

console.log(floatEqual(0.1 + 0.2, 0.3)); // true

这个方法简单有效,适合大多数场景。不过 epsilon 的值得根据实际情况选,太小可能还是判不等,太大又容易误判。

根据业务需求调整精度

比如做金额计算,通常只关心到分(两位小数)。这时候可以把数字放大 100 倍转成整数再比:

function moneyEqual(a, b) {
return Math.round(a * 100) === Math.round(b * 100);
}

console.log(moneyEqual(0.1 + 0.2, 0.3)); // true

这样就避开了浮点误差,还符合日常对钱的处理习惯。

语言内置方案参考

有些语言提供了专门处理浮点比较的方法。比如 Python 的 math.isclose()

import math
math.isclose(0.1 + 0.2, 0.3) # True

JavaScript 虽然没有原生函数,但可以用上面自定义的方式实现类似效果。

浮点数比较不是难题,关键是意识到它不能像整数那样简单处理。只要加一层判断逻辑,就能避免很多隐藏 bug。下次写代码时,看到浮点数比较,先停一下,想想是不是该用容差了。