c++中如何比较浮点数是否相等_c++判断两个double是否相等【汇总】

3次阅读

应使用相对误差加绝对误差组合判断 double 相等,而非 ==;因浮点数是二进制近似表示,0.1+0.2≠0.3 是 IEEE 754 固有特性。

c++ 中如何比较浮点数是否相等_c++ 判断两个 double 是否相等【汇总】

直接用 == 比较两个 double 几乎总是错的

因为浮点数在 计算机 中是二进制近似表示,0.1 + 0.2 != 0.3 是常态。用 == 判断相等,哪怕数值上“看起来一样”,也可能返回 false。这不是 bug,是 IEEE 754 的固有特性。

用相对误差 + 绝对误差组合判断(推荐通用方案)

单一阈值(如 abs(a - b))在极小值或极大值场景下会失效:对接近 0 的数太松,对超大数(如 1e20)又太严。工业级做法是同时检查相对和绝对误差:

bool double_equal(double a, double b, double abs_tol = 1e-9, double rel_tol = 1e-9) {double diff = std::abs(a - b);     double max_abs = std::max(std::abs(a), std::abs(b));     return diff <= abs_tol || diff <= rel_tol * max_abs;}
  • abs_tol 防止 ab 都接近 0 时除零或误判
  • rel_tol 控制相对精度,适合非零数量级的比较
  • C++20 起可直接用 std::absstd::max,无需手动处理符号
  • 若确定不会出现 NaNinf,可省略额外检查;否则需先用 std::isnan()std::isinf() 过滤

使用 std::numeric_limits::epsilon() 的常见误解

epsilon() 表示 1.0 附近的最小可表示差值(约 2.22e-16),** 不能直接用于任意数值的比较 **。它不是全局精度阈值:

  • abs(a - b) ::epsilon() 只在 ab 接近 1.0 时有意义
  • 1e10 量级的数,相邻可表示值间距已是 1e-6 级别,此时用 epsilon 会过度严格
  • 正确用法是:abs(a - b) ::epsilon() * std::max(abs(a), abs(b)) —— 这其实就是上面 rel_tol 的特例

测试时如何避免浮点比较陷阱

单元测试中尤其容易踩坑。不要写 EXPECT_EQ(a, b)(Google Test)或 assert(a == b)

立即学习C++ 免费学习笔记(深入)”;

  • 改用 Google Test 提供的 EXPECT_DOUBLE_EQ(a, b)(内部用 4 * DBL_EPSILON * max(|a|,|b|)
  • 或自定义断言宏,强制走你验证过的容差逻辑
  • 对计算结果做“四舍五入再比较”看似简单,但会掩盖精度损失问题,不建议作为通用解法
  • 如果业务允许,考虑用整数运算替代(如金额存为 int64_t 分)——这是最彻底的规避方式

真正麻烦的不是写对一次比较,而是确保整个代码库、所有测试、所有边界输入都统一用同一套语义。漏掉一个 ==,就可能让 bug 潜伏数月。

text=ZqhQzanResources