在现代 C++ 中比较 double/float 是否相等的现代实践

Modern practice to compare double/float for equality in modern C++

if (std::abs(double1 - double2) < std::numeric_limits<double>::epsilon())
  std::cout<<"Equal";
else
  std::cout<<"Not equal";

这段代码与现代 C++11/14/17/21 是否仍然是我们比较浮点数和双精度数的方式,或者现在只写就可以了

if (double1 == double2)

编译器会为我们处理 epsilon 问题吗?

顺便说一句:检查 epsilon 时写 < 或 <= 哪个更好?

Is this code with modern C++11/14/17/21 is still the way we should compare float and doubles, or now it's ok just to write if (double1 == double2) And compiler will handle the epsilon issue for us?

这两种方法在现代 C++ 中的作用与在早期 C++ 中的作用相同

这两种方法都存在缺陷。

  • 使用 == 假设您的代码已经解决了任何浮点舍入错误,代码做到这一点非常 rare/difficult。

  • 与 epsilon 比较假设合理的舍入误差量将小于常量 epsilon,这很可能是错误的假设!

    • 如果你的数字的大小 大于 2.0,你的 epsilon 技巧与直接比较没有什么不同,并且有同样的缺陷。无论您使用 < 还是 <=.
    • 如果你的数字有相同的符号并且大小 小于 epsilon,你的 epsilon 技巧会说它们总是相等的,即使一个比另一个大数百倍.它们也都等于零。

明智的做法可能是避免编写依赖于浮点数是否相等的代码。而是测试它们是否 相对 接近,由某种因素决定。

下面的代码将测试两个数字之间的误差是否在 0.01% 以内。不管规模如何。

const auto relative_difference_factor = 0.0001.    // 0.01%
const auto greater_magnitude = std::max(std::abs(double1),std::abs(double2));

if ( std::abs(double1-double2) < relative_difference_factor * greater_magnitude )
  std::cout<<"Relatively close";
else
  std::cout<<"Not relatively close";