应使用容差值(epsilon)进行近似比较而非===,因浮点数二进制表示存在精度误差;常用方法为判断math.abs(a - b)

JavaScript 中直接用 === 或 == 比较两个浮点数是否相等,常常会得到意外结果,比如 0.1 + 0.2 === 0.3 返回 false。这是因为浮点数在二进制中无法精确表示某些十进制小数,存在精度误差。正确做法是判断两数之差的绝对值是否小于一个极小的容差值(epsilon)。
使用固定容差值进行近似比较
这是最常用、最直观的方式:定义一个足够小的阈值(如 1e-10),检查两数差值是否落在该范围内。
- 容差值通常取
Number.EPSILON(约2.22e-16),但注意它适用于1附近的数;对较大或较小的数值,需按比例调整 - 更稳妥的做法是用相对误差:比较
Math.abs(a - b) - 简单场景下可直接用
Math.abs(a - b) ,适合大多数业务逻辑(如金额、坐标、物理模拟)
封装成可复用的比较函数
避免每次手动写容差逻辑,封装一个健壮的 floatEqual 函数:
- 支持传入自定义 epsilon,兼顾灵活性和默认安全
- 处理
NaN和Infinity等边界情况(例如NaN !== NaN,需单独判断) - 示例:
function floatEqual(a, b, epsilon = Number.EPSILON * 10) {<br> if (Number.isNaN(a) || Number.isNaN(b)) return false;<br> return Math.abs(a - b) }
注意数值范围对容差的影响
固定容差(如 1e-10)在数值极大或极小时可能失效:
- 比如比较
1e20和1e20 + 1,差值1远大于1e-10,但实际在浮点精度下这两个数可能被视作相等 - 此时应采用相对容差:以两数数量级为基准动态计算容差,例如
epsilon * Math.max(Math.abs(a), Math.abs(b), 1) - 若涉及科学计算,推荐使用专门库如 robust-arithmetic 处理高精度运算
避免常见误区
有些看似“巧妙”的写法反而引入新问题:
- 不要用
Math.round(x * 100) / 100后再比较——四舍五入本身也受浮点误差影响,且会改变原始语义 - 不要依赖
toFixed()转字符串比较——它返回字符串,且对1.005等数的舍入行为不一致 - 不要把所有浮点比较都换成整数运算(如乘以 100 处理金钱)——这仅适用于已知小数位数的场景,不具通用性
浮点数比较本质是误差控制问题,关键不是“完全相等”,而是“在当前上下文下是否足够接近”。选对容差策略,比追求理论上的精确更重要。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











