在现代 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";
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";