C ++中的“==”为相同的双精度赋予_sometimes_不同的结果

时间:2013-12-16 10:41:34

标签: c++ floating-point double

以下是代码:

#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;

据我所知,double的精度有限(15位),加/减1的运算对于这么大的数字没有多大意义。但我希望“==”操作总是给出'true'然后作为结果。事实并非如此。

有时会发生第18行中的两个双精度不相等( scaleMin == scaleMax ),并且几行之后它们相等(即触发第27行中的断言)。这些数字总是一样的(1.6170737412027187 e17)

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

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

行为仍然相同。有什么想法吗?

2 个答案:

答案 0 :(得分:2)

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

例如,在x86上,默认情况下(尽管你可以change this),FPU寄存器对80位尾数的值执行计算,当值作为IEEE存储在内存中时会被截断为53位双打。

因此,在优化代码中,由于可能无关的代码需要寄存器或由于您无法控制的其他原因,因此它们会被刷新到内存中,因此在C行之间看起来会略微发生变化。 / p>

因此,您通常不能将==用于示例代码等目的。

答案 1 :(得分:-2)

你不能对浮点数和双打数使用精确的等式检查。

即使在您执行以下操作的情况下:

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
    // ...
}