PVS-Studio жалуется на сравнение с плавающей точкой

Я отсканировал свой код с помощью анализатора PVS Studio, и я не понимаю, почему эта ошибка и как ее исправить.

V550 Странное точное сравнение: * dest == value. Вероятно, лучше использовать сравнение с определенной точностью: fabs (A — B) < Эпсилон.

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

1

Решение

Кто бы ни задавался вопросом, мы говорим о этот код.

Я попытаюсь объяснить, чего разработчики студии 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’ зависит от процессора, версии компилятора и используемых настроек. Например, значение переменной ‘b’ было 0,49999999999999994, когда мы использовали компилятор Visual C ++ 2010.

То, что они пытаются сказать, это сравнение чисел с плавающей запятой сложно. Если вы просто присваиваете число с плавающей запятой, сохраняйте его и перемещайте по памяти, чтобы потом сравнить с собой в этой функции — не стесняйтесь отклонять это сообщение об ошибке.

Если вы хотите выполнить некоторую проверку битового представления (что, честно говоря, вы делаете), увидеть ниже.

Если вы выполняете какие-то масштабные вычисления для чисел с плавающей запятой, и вы являетесь разработчиком игры, вычисляя координаты вражеских линейных крейсеров — это предупреждение является одним из ваших лучшие друзья.


В любом случае, вернемся к вашему делу. Как это обычно бывает с PVS-Studio, они не увидели точную ошибку, но указали вам верное направление. Вы на самом деле хочу сравнить два значения с плавающей точкой, но вы делаете это неправильно. Дело в том, что если оба сравниваемых числа с плавающей запятой содержат NaN (даже в одном и том же битовом представлении), вы получите *dest != value, и ваш код не будет работать так, как вы хотите.

В этом случае лучше переосмыслить память под float * как uint32_t (или любой другой целочисленный тип имеет тот же размер, что и float на вашей цели) и сравнить их вместо.

Например, в вашем конкретном случае, register_file_->values[register_name] имеет тип xe::gpu::RegisterFile::RegisterValue, который уже поддерживает uint32_t представление.

Как побочный эффект, это уберет предупреждение 🙂

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]