不能直接用==比较浮点数,因为浮点数在计算机中按ieee 754标准以二进制近似存储,导致0.1+0.2≠0.3等精度丢失;舍入误差使数值差几个ulp,故须用epsilon容差比较绝对差值。

为什么不能直接用 == 比较浮点数
浮点数在计算机中以二进制近似存储,0.1 + 0.2 不等于 0.3 是经典表现。直接用 == 判断两个 float 或 double 是否“相等”,几乎总会出错——哪怕它们是同一计算路径得出的结果。
根本原因是:舍入误差累积后,数值可能差几个 ULP(Unit in the Last Place),但肉眼看起来“一样”。所以必须引入容差(epsilon)做相对或绝对比较。
用 std::abs(a - b) 这是最常用、也最容易理解的方式,适用于数值量级已知且不会过大或过小的场景。
实操建议:
- 选一个合适的
epsilon:对double常用1e-9或std::numeric_limits<double>::epsilon()</double>(约2.2e-16),但注意后者是“1.0 的最小可表示增量”,不是通用容差 - 避免用
std::numeric_limits<t>::epsilon()</t>直接当容差:它太小,只适用于与1.0同量级的数;比较1e6级别的数时,需放大 epsilon - 示例:
double a = 0.1 + 0.2;<br>double b = 0.3;<br>if (std::abs(a - b)
用相对误差判断更鲁棒的场景
当两个数可能很大(如 1e10)或很小(如 1e-10)时,固定 epsilon 会失效:太大则误判,太小则漏判。
实操建议:
- 公式:
std::abs(a - b) - 必须处理
a和b都为 0 的情况(否则除零风险),或改用std::abs(a - b) - 更稳妥的做法是组合绝对+相对:先用绝对误差兜底(防接近零时崩溃),再用相对误差覆盖正常范围
- 示例:
bool approx_equal(double a, double b, double eps = 1e-9) {<br> double diff = std::abs(a - b);<br> double max_val = std::max(std::abs(a), std::abs(b));<br> return diff }
别忽略 NaN 和无穷大的特殊行为NaN 与任何值(包括自身)用 == 比较都返回 false,而 std::abs(NaN) 仍是 NaN,参与比较会导致整个表达式结果不可靠。
实操建议:
- 调用前先用
std::isnan(a) || std::isnan(b)检查,若任一为NaN,通常应直接返回false(除非业务明确要求 NaN 视为相等) -
std::isinf(a)和std::isinf(b)要单独处理:同号无穷大可视为相等,异号则不等 - 标准库不提供开箱即用的“安全浮点比较”,自己封装函数时务必把
NaN和inf分支写清楚
实际项目里,浮点比较的“正确性”高度依赖上下文:物理仿真容忍 1e-6,金融计算可能要 1e-12,而图形学中向量归一化后的点积误差常取 1e-5。没有银弹,只有根据量纲、精度需求和输入范围选合适策略。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










