C++常见问题精简版"[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的建议用途有限。 没有“一刀切”的浮点比较。 您必须考虑变量的语义,可接受的值范围以及计算引入的误差幅度。甚至FAQ也提到了一个警告,说“当x和y的幅度明显大于epsilon,但里程可能会有所不同时”,此功能通常不是问题。
关于c++ - 比较浮点数为零,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19837576/