C++ FAQ 精简版 "[29.17] Why doesn't my floating-point comparison work?"推荐这个平等测试:
#include <cmath> /* for std::abs(double) */
inline bool isEqual(double x, double y)
{
const double epsilon = /* some small number such as 1e-5 */;
return std::abs(x - y) <= epsilon * std::abs(x);
// see Knuth section 4.2.2 pages 217-218
}
- 这是否正确,这意味着唯一等于零的数字是
+0
和-0
? - 在测试零或者更确切地说是像
|x| < epsilon
这样的测试时,是否也应该使用此功能? ?
更新
正如 Daniel Daranas 所指出的,该函数最好称为 isNearlyEqual
。 (这是我关心的情况)。
有人指出"Comparing Floating Point Numbers" ,我想更突出地分享。
最佳答案
您的观察是正确的。
如果 x == 0.0
,然后 abs(x) * epsilon
为零,您正在测试是否 abs(y) <= 0.0
.
如果 y == 0.0
那么你正在测试 abs(x) <= abs(x) * epsilon
这意味着 epsilon >= 1
(不是)或x == 0.0
.
所以is_equal(val, 0.0)
或 is_equal(0.0, val)
没有意义,你可以说val == 0.0
.如果您只想完全接受 +0.0
和 -0.0
.
在这种情况下,FAQ 的建议是有限的。 没有“一刀切”的浮点比较。您必须考虑变量的语义、可接受的值范围以及计算引入的误差幅度。甚至常见问题解答都提到了一个警告,说这个函数通常不是问题“当 x 和 y 的大小明显大于 epsilon 时,但你的里程可能会有所不同”。
关于c++ - 将 float 与零进行比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19837576/