与具有浮点值的 0.0 进行比较

Comparison to 0.0 with floating point values

使用浮点数时,有时会出现舍入问题。因此,通常不建议将计算结果与 == 或 != 进行比较,而是使用适当的界限,如 abs(a-b)<1.0e-10.

但是用它来比较 0.0 合适吗?

这就是我所说的:

double foo(){
    //code which can return values that aren't 0.0
    //all returns are either literals or global variables defined with literals
    return 0.0;
}

此处 f 将始终 return 恰好 0.0 或明确不是 0.0 的数字。具体来说,这些数字的大小都将大于 0.1 但小于 2.0.

如果 return 是 0.00.0==foo() 会一直是 true 吗?如果 foo return 是 0.0 以外的值,0.0==foo() 是否有可能成为 true

最多 std::numeric_limits::digits<float> 你是安全的。这是因为尾数是整数类型(通常是特定于平台的 uint;然后通过符号位和指数扩展为浮点数)。

http://en.cppreference.com/w/cpp/types/numeric_limits/digits

如果你 return 一个文字 0.0 那么是的,但这通常不是一个好主意,因为虽然今天是这样,但你能确定在维护或代码重用下它会保持真实。最好编写一些可以在更广泛的环境中工作的代码。在这种情况下:

foo() < 0.1
对于您指定的所有值,

将 return 为假。更通用的解决方案是测试是否足够接近零:

static const EPSILON = 0.00001 ;
std::fabs( foo() - 0.0 ) < EPSILON ; 

最好使用上述模式之一,因为它不需要foo()对"zero"的精度做出任何保证。

在你的情况下使用浮点相等是完全正确的== 0.0

它完全符合函数的意图(return 某个值,如果失败则为 0.0)。使用任何其他 epsilon 在某种程度上是任意的,并且需要了解正确值的范围。如果有什么事情发生变化,很可能是值的范围而不是 0,所以测试 == 0.0 与 IMO 的其他解决方案相比不亚于未来的证明。

我看到的唯一问题是一些编译器会警告相等性 (-Wfloat-equal) 的可疑使用...这与警告 int a,b,c; ...; c=a+b; 一样有用,因为这样的指令可能会导致问题 (整数溢出和未定义的行为)。奇怪的是,我从来没有看到第二个警告。

因此,如果您想使用 -Wall -Werror 编译器选项来证明未来,您可以对失败进行不同的编码(例如使用负值)并测试 foo < 0.0 - 直到有人发现浮点不等式可能也需要容忍度,并将构造声明为可疑。