PVS-Studio抱怨浮点比较

PVS-Studio complaining about float comparison

本文关键字:比较 PVS-Studio      更新时间:2023-10-16

我用PVS Studio分析仪扫描了我的代码,我对为什么会出现此错误以及如何解决此问题感到困惑。

V550 一个奇怪的精确比较:* dest == 值。最好使用具有定义精度的比较:fabs(A - B( <Epsilon。>

bool PipelineCache::SetShadowRegister(float* dest, uint32_t register_name) {
float value = register_file_->values[register_name].f32;
if (*dest == value) {
return false;
}
*dest = value;
return true;
}

我猜要像这样更改代码:

bool PipelineCache::SetShadowRegister(float* dest, float* epsilon uint32_t register_name) {
float value = register_file_->values[register_name].f32;
return fabs(dest - value) < epsilon;
}

无论谁想知道,我们都在谈论这段代码。

我将尝试解释 PVS 工作室开发人员试图通过此消息实现的目标。引用他们对V550的参考:

请考虑以下示例:

double a = 0.5;
if (a == 0.5) //OK
x++;
double b = sin(M_PI / 6.0);
if (b == 0.5) //ERROR
x++;

第一个比较 'a == 0.5' 是正确的。第二个比较 'b == 0.5' 可能既正确又错误。'b == 0.5' 表达式的结果取决于处理器、编译器的版本和所使用的设置。例如,当我们使用 Visual C++ 2010 编译器时,'b' 变量的值为

0.499999999999994。

他们想说的是,比较浮点数是棘手的。如果您只是分配浮点数,请存储它并在内存中移动它,以便稍后在此函数中与自身进行比较 - 请随时关闭此错误消息。

如果你想执行一些位表示检查(老实说,我认为你正在这样做(,见下文

如果您正在对浮点数进行大量计算,并且您是游戏开发人员,正在计算敌方战列巡洋舰的坐标 - 此警告是您最好的朋友之一。


无论如何,让我们回到你的案例。正如PVS-Studio通常发生的那样,他们没有看到确切的错误,但他们为您指出了正确的方向。您实际上比较两个浮点值,但您做错了。问题是,如果您正在比较的两个浮点数都包含 NaN(即使在相同的位表示中(,您也会得到*dest != value,并且您的代码将无法以您想要的方式工作。

在这种情况下,最好将float *下的内存重新解释为uint32_t(或任何整数类型与目标上的float大小相同的整数类型(并进行比较。

例如,在您的特定情况下,register_file_->values[register_name]属于xe::gpu::RegisterFile::RegisterValue类型,它已经支持uint32_t表示。

作为副作用,这会将警告引开:)