直接用==比较float或double几乎总是错的,因为0.1+0.2在内存中实际存储为0.30000000000000004,而0.3也是近似值,二者二进制表示不同导致==返回false;这是ieee 754标准下浮点数固有精度限制所致,非程序bug。

直接用 == 比较 double 或 float 几乎总是错的
因为 0.1 + 0.2 在内存里实际是 0.30000000000000004,而 0.3 存储的也是近似值,两者二进制表示不同,== 返回 false。这不是 bug,是 IEEE 754 浮点表示的必然结果。一旦涉及计算、读取文件、跨平台传输或多次运算,误差就更不可控。
绝对误差 std::abs(a - b) 适合什么场景
这是最常用也最容易上手的方式,但只在两个数数量级接近(比如都在 1e-3 到 1e3 范围内)时可靠。
-
eps = 1e-9对double是常见起点,适用于多数科学计算、几何坐标比较 -
eps = 1e-5或1e-6更适合float(如图形管线、嵌入式传感器数据) - 别硬套
DBL_EPSILON(约2.2e-16):它表示 1.0 附近可分辨的最小差值,不是通用容差;拿它去比1e10和1e10 + 1会失效 - 对接近零的数(如
1e-15),绝对误差法仍可用,但需确保eps大于该数量级的典型舍入噪声
相对误差 std::abs(a - b) 更鲁棒
当数值跨度大(比如同时处理 1e-8 的物理常量和 1e12 的天体质量),绝对误差会失衡。相对误差让容差随数值本身缩放。
- 必须加兜底:如果
a和b都接近零,分母趋近于 0,结果爆炸。实际写法要先判断是否“都小”,再切到绝对误差分支 - 示例逻辑:
bool nearly_equal(double a, double b, double eps = 1e-9) { double diff = std::abs(a - b); double max_abs = std::max(std::abs(a), std::abs(b)); if (max_abs - 注意:相对误差对符号相反的数(如
a=1e5,b=-1e5)不适用——此时差值是2e5,但相对尺度失去意义,应退回到绝对误差
epsilon 设置容易被忽略的三个细节
很多人调完 1e-9 就以为万事大吉,但真实项目里这几个点常导致偶发失败:
- 不同编译器 / 标准库对
std::abs的重载行为略有差异,#include <cmath></cmath>必须显式包含,否则可能隐式转成 int 版本导致截断 - 混合使用
float和double时,1e-9对float过严(float有效位仅 6–7 位),建议统一用double,或为float单独设1e-5 - 如果浮点数来自外部(如 JSON 解析、CSV 导入),其精度可能已被字符串转浮点过程二次污染,这时误差可能比理论值大一个数量级,需要实测日志观察
a - b的典型分布再定eps
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











