直接用 == 比较浮点数几乎总是错误的,因浮点数在计算机中为近似表示,存在舍入误差(如 0.1 + 0.2 ≠ 0.3),且受编译器、优化及精度限制(float 约 6–7 位,double 约 15–17 位)影响,应改用 std::abs(a - b) 判断误差范围。

直接用 == 比较两个 float 或 double 几乎总是错的。浮点数在计算机中是近似表示,哪怕数学上相等的计算结果,二进制存储也可能有微小误差。
为什么 == 不可靠
浮点运算是有舍入误差的。比如 0.1 + 0.2 在 IEEE 754 下不等于 0.3(实际是 0.30000000000000004),所以 (0.1 + 0.2) == 0.3 返回 false。
- 不同编译器、优化级别、甚至寄存器使用方式都可能改变中间结果的精度
-
float约 6–7 位有效数字,double约 15–17 位,超出即失真 - 绝对误差和相对误差行为不同:大数的绝对误差大,小数的相对误差易失控
用 std::abs(a - b) 是最常用解法
判断两浮点数“足够接近”,而不是“完全相等”。关键是选对 epsilon 值:
- 对数量级已知的值(如单位区间内计算),可用固定小值:
1e-6(float)或1e-9(double) - 更健壮的做法是用相对误差:
std::abs(a - b) ::epsilon() * std::max(std::abs(a), std::abs(b)) -
std::numeric_limits<t>::epsilon()</t>表示 1.0 可表示的最小增量,不是万能阈值——它只适用于接近 1 的数 - 注意:当
a和b接近 0 时,相对误差会失效,需回退到绝对误差判断
推荐封装成可复用的比较函数
避免每次手写逻辑出错。一个兼顾大小数、避免除零、不依赖宏的轻量实现:
立即学习“C++免费学习笔记(深入)”;
bool approx_equal(double a, double b, double abs_eps = 1e-9, double rel_eps = std::numeric_limits<double>::epsilon()) {
double diff = std::abs(a - b);
if (diff <= abs_eps) return true;
double scale = std::max(std::abs(a), std::abs(b));
return diff <= scale * rel_eps;
}- 默认
abs_eps覆盖接近零的情况;rel_eps处理一般范围 - 不用
std::isfinite等额外检查,但实际项目中建议先过滤NaN和无穷大(std::isnan(a) || std::isnan(b)必须返回false) - 不要把
epsilon设得比运算本身误差还小——比如对经过 10 次乘加的double结果,1e-15往往不现实
真正难的不是写这个函数,而是每次做浮点比较前,想清楚:这个“相等”在业务上意味着什么?容忍多大误差?是否涉及用户输入、物理单位换算、或迭代收敛判断?这些决定了 epsilon 该取 1e-3 还是 1e-12,而不是套用某个“标准值”。










