问题描述
if (std::abs(double1 - double2) < std::numeric_limits<double>::epsilon())
std::cout<<"Equal";
else
std::cout<<"Not equal";
这段代码与现代 C++11/14/17/21 是否仍然是我们应该比较 float 和 doubles 的方式,或者现在只需编写就可以了
if (double1 == double2)
编译器会为我们处理 epsilon 问题吗?
顺便说一句:在检查 epsilon 时写
解决方法
这段代码是否与现代 C++11/14/17/21 仍然是我们应该比较浮点和双精度的方式,或者现在只需编写 if (double1 == double2)
就可以了,编译器会为我们处理 epsilon 问题?
这两种方法在现代 C++ 中的功能与在早期 C++ 中的功能相同。
这两种方法都有缺陷。
-
使用
==
假定您的代码已经考虑了任何浮点舍入错误,而代码做到这一点非常罕见/困难。 -
与 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";