假设两个浮点数x和y都不是Nan。
是否可以安全地假设平等和不平等测试将:
一种。彼此保持一致:
例如。是否保证以下内容是正确的:(x >= y) == ((x > y) || (x == y))
b。可重复
例如。如果x和y都未更改,则(x == y)
始终在每次评估时都给出相同的结果。
我之所以问这个问题,是因为浮点单元可以以更高的精度将中间结果存储在内存中,因此,变量的值可能会改变,具体取决于它是否是最近计算的结果,仍然在FPU中,或者它是否来自内存。可以想象,第一个测试可能在前一种情况下,而后一个测试则在后一种情况下。
最佳答案
如果问题中的x
和y
是标识符(通常不是表达式的缩写,例如x
代表b + sqrt(c)
),那么C++标准要求(x >= y) == (x > y || x == y)
为true。
C++ 2017(N4659草稿)8 13允许以比其标称类型所需的精度和范围更大的精度和范围来计算浮点表达式。例如,在使用float
操作数评估运算符时,该实现可以使用double
算法。但是,脚注64指向我们8.4、8.2.9和8.18,以了解强制转换和赋值运算符必须执行其特定的转换,这些转换产生的值可以名义类型表示。
因此,一旦为x
和y
分配了值,就不会有过多的精度,并且它们在不同的用途中也不会具有不同的值。然后(x >= y) == (x > y || x == y)
必须为true,因为它会在出现时进行评估,并且在数学上必须为true。
GCC bug 323的存在意味着您无法为i386编译时依赖GCC,但这是由于GCC中的一个漏洞违反了C++标准。标准C++不允许这样做。
如果在表达式之间进行比较,例如:
double y = b + sqrt(c);
if (y != b + sqrt(c))
std::cout << "Unequal\n";
则分配给
y
的值可能与为b + sqrt(c)
的右运算符计算的值不同,并且可能会打印字符串,因为b + sqrt(c)
可能具有过高的精度,而y
一定没有。由于还需要使用强制类型转换来消除多余的精度,因此
y != (double) (b + sqrt(c))
始终应为false(根据上面y
的定义)。
关于c++ - 是否可以假定浮点相等性和不相等性测试是一致且可重复的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59768483/