"==" in C++ 为相同的双打提供_有时_不同的结果

"==" in C++ gives _sometimes_ different results for the same doubles

本文关键字:有时 结果 C++ in      更新时间:2023-10-16

以下是代码:

#define MIN_RESOLUTION          ( 0.0000001)
double yMax, yMin;
// calculate yMax, yMin
//....
if( fabs( yMax - yMin) > MIN_RESOLUTION)
{ 
    scaleMin = yMin;
    scaleMax = yMax;
}
else
{ 
    // following two lines are executing
    scaleMin = yMin - 1.0;
    scaleMax = yMax + 1.0;
    // could still be the same...
    if(scaleMin == scaleMax)
    {
        if(scaleMax > 0) // decrease min
            scaleMin = 0;
        else             // increase max
            scaleMax = 0;
    }
}
assert(scaleMin != scaleMax);

在我的示例yMin == yMax == 1.6170737412027187 e17。正因为如此,第14行和第15行始终执行:

  scaleMin = yMin - 1.0;
  scaleMax = yMax + 1.0;

我知道双精度是有限的(15位),加/减1的运算对这么大的数字没有多大意义。但我希望"=="运算总是给出"true"作为结果。事实并非如此。

有时,第18行中的两个双精度不相等(scaleMin=scaleMax),并且几行之后它们相等(即,触发第27行中的断言)。数字完全相同(1.6170737412027187 e17)

我也试着用这个替换第(27)行:

if (scaleMin == scaleMax)
{
    assert(false);
}

行为仍然是一样的。有什么想法吗?

请记住,浮点值在寄存器中的表示不一定与内存中的表示相同。

例如,在x86上,默认情况下(尽管您可以更改此设置),FPU寄存器对尾数为80位的值执行计算,当IEEE加倍时,这些值存储在内存中时,尾数将被截断为53位。

因此,在优化的代码中,由于潜在的不相关代码需要寄存器或其他不受您控制的原因,当值被刷新到内存时,C行之间的值完全有可能出现轻微变化。

正因为如此,您通常不能将==用于示例代码之类的目的。

不能对浮点和双精度使用精确相等检查。

即使在这样的情况下:

float a = calculate_sin_in_0();
float b = calculate_cos_in_pi_2();

由于机器的工作方式,a和b的值可能略有不同

要正确执行这样的检查,您必须将一些小值视为无关紧要:

const float eps = 0.00001;
if (abs(a - b) < eps) {  // consider a == b
    // ...
}