Почему Splint (средство проверки кода C) выдает ошибку при сравнении числа с плавающей точкой и int?

#c #lint #splint

Вопрос:

Оба являются математическими значениями, однако поплавок имеет большую точность. Это единственная причина ошибки — разница в точности? Или есть другая потенциальная (и более серьезная) проблема?

Ответ №1:

Это связано с тем, что набор целочисленных значений не равен набору значений с плавающей точкой для типов » int » и «float». Например, значение с плавающей точкой 0,5 не имеет равных в целочисленном наборе, а целочисленное значение 4519245367 может не существовать в наборе значений, которые может хранить поплавок. Таким образом, средство проверки помечает это как проблему, которую должен проверить программист.

Ответ №2:

Потому что это, вероятно, не очень хорошая идея. Не все поплавки могут быть усечены до int; не все int могут быть преобразованы в поплавки.

Ответ №3:

При выполнении сравнения целочисленное значение будет «повышено» до значения с плавающей запятой. В этот момент вы проводите точное сравнение равенства между двумя числами с плавающей запятой, что почти всегда плохо.

Как правило, у вас должен быть какой-то «шар эпсилона» или диапазон допустимых значений, и вы проводите сравнение, если два вау достаточно близки друг к другу, чтобы считаться равными. Вам нужна функция примерно такая:

 int double_equals(double a, double b, double epsilon)
{
   return ( a > ( b - epsilon ) amp;amp; a < ( b   epsilon ) );
}
 

Если в вашем приложении нет очевидного выбора epsilon, используйте DBL_EPSILON.

Комментарии:

1. Предупреждение: в функции double_equals отсутствует важное свойство «регулярного» равенства. Это не является переходным. (При регулярном равенстве, если x == y и y == z, то x == z. Это больше не верно при использовании double_equals.)

Ответ №4:

Поскольку поплавки не могут хранить точное значение int, поэтому, если у вас есть две переменные, int i и float f, даже если вы назначите «i = f;», сравнение «если (i == f)», вероятно, не вернет значение true.

Ответ №5:

Предполагая целые числа со знаком и формат IEEE с плавающей запятой, значения целых чисел, которые могут быть представлены, являются:

 short  -> 15 bits
float  -> 23 bits
long   -> 31 bits
double -> 52 bits
 

Следовательно, a float может представлять любое short , и a double может представлять любое long .

Ответ №6:

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