【问题标题】:Modern practice to compare double/float for equality in modern C++ [duplicate]在现代 C++ 中比较 double/float 是否相等的现代实践 [重复]
【发布时间】:2021-08-22 19:34:32
【问题描述】:
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 时写

【问题讨论】:

  • 这与现代或非现代无关,但任何一种方式都可能是对的或错的,这取决于你真正想要什么。 == comares 是平等的,还有doubles,你只需要知道这是否真的想要你想要的
  • 是的,它仍然是这样做的。原因见:stackoverflow.com/questions/588004/…
  • 编译器会为我们处理 epsilon 问题? 不,它仍然会按照你说的做。
  • 不,没有变化。 C++ 的主要目标之一是性能,并且进行 epsilon 检查比不进行检查更昂贵,因此默认运算符不会这样做。如果要与 epsilon 进行比较,则必须自己进行。
  • 如果你想检查是否相等,== 一直是你需要使用的。如果您想检查近似相等,您需要首先确定您的意思(100000000100000001 是否近似相等?0.0000010.0000000001 是否近似相等?这实际上取决于上下文)。跨度>

标签: c++ c++11 floating-point


【解决方案1】:

现代 C++11/14/17/21 的这段代码是否仍然是我们应该比较浮点数和双精度数的方式,还是现在只需编写 if (double1 == double2) 就可以了,编译器将为我们处理 epsilon 问题?

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

这两种方法都有缺陷。

  • 使用== 假定您的代码已经考虑了任何浮点舍入错误,并且代码很少/很难做到这一点。

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

    • 如果您的数字的幅度大于2.0,那么您的 epsilon 技巧将与直接比较没有什么不同,并且具有相同的缺陷。无论您使用&lt; 还是&lt;=
    • 如果您的数字具有相同的符号且幅度小于 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";

【讨论】:

    猜你喜欢
    • 2014-09-29
    • 1970-01-01
    • 2011-10-10
    • 1970-01-01
    • 2012-10-03
    • 2018-11-30
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    相关资源
    最近更新 更多