Floating point comparison with equality operators

Неточное сравнение переменных с плавающей точкой

Описание

Сравнение с плавающей точкой с операторами равенства происходит, когда вы используете равенство (==) или неравенство (!=) операция с числами с плавающей запятой.

Polyspace® не повышает дефект для операции равенства или неравенства с числами с плавающей запятой когда:

  • Сравнение между двумя константами плавающими.

        float flt = 1.0;
        if (flt == 1.1)
  • Сравнение между константой и переменной, которая может взять конечное, обоснованно небольшое количество значений.

    float x;
    
    int rand = random(); 
    switch(rand) { 
    case 1: x = 0.0; break; 
    case 2: x = 1.3; break; 
    case 3: x = 1.7; break; 
    case 4: x = 2.0; break; 
    default: x = 3.5; break; }
    …
    if (x==1.3) 
  • Сравнение между выражениями с плавающей точкой, которые содержат только целочисленные значения.

    float x = 0.0;
    for (x=0.0;x!=100.0;x+=1.0) {
    …
    if (random) break;
    }
    
    if (3*x+4==2*x-1)
    …
    if (3*x+4 == 1.3)
  • Одним из операндов является 0.0, если вы не используете флаг -detect-bad-float-op-on-zero опции.

    /* Defect detected when
    you use the option flag */
    
    if (x==0.0f) 

    Если при запуске анализ через пользовательский интерфейс, можно ввести эту опцию в поле Other под узлом Advanced Settings на панели Configuration. Смотрите Other.

    В командной строке добавьте флаг в свою аналитическую команду.

    polyspace-bug-finder -sources filename ^
    -checkers BAD_FLOAT_OP -detect-bad-float-op-on-zero

Риск

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

Фиксация

Вместо того, чтобы проверять на равенство значений с плавающей точкой:

if (val1 == val2)
проверяйте, меньше ли их различие предопределенного значения допуска (например, значение FLT_EPSILON заданный в float.h):
#include <float.h>
if(fabs(val1-val2) < FLT_EPSILON)

Смотрите примеры мер ниже.

Если вы не хотите устранять проблему, добавьте комментарии в свой результат или код, чтобы избежать другого анализа. Смотрите Результаты Polyspace Адреса Через Исправления ошибок или Выравнивания.

Примеры

развернуть все

#include <stdio.h>
#include <math.h>
#include <float.h>

void func(void)
{
    float f;
    for (f = 1.0; f != 2.0; f = f + 0.1)    
        (void)printf("Value: %f\n", f);
}

В этой функции, for- цикл тестирует неравенство f и номер 2.0 как останавливающийся механизм. Количество итераций затрудняет, чтобы определить или может быть бесконечным из-за неточности в представлении с плавающей точкой.

Коррекция — изменяет оператор

Одна возможная коррекция должна использовать различный оператор, который не так строг. Например, неравенство как >= или <=.

#include <stdio.h>
#include <math.h>
#include <float.h>

void func(void)
{
    float f;
    for (f = 1.0; f <= 2.0; f = f + 0.1)    
        (void)printf("Value: %f\n", f);
}

Проверяйте информацию

Группа: Программирование
Язык: C | C++
Значение по умолчанию: 'off'
Синтаксис командной строки: BAD_FLOAT_OP
Удар: носитель
ID CWE: 873

Введенный в R2013b