exponenta event banner

CERT C: Rec. FLP02-C

Избегайте использования чисел с плавающей запятой при необходимости точного вычисления

Описание

Определение правила

Избегайте использования чисел с плавающей запятой при необходимости точного вычисления. [1 ]

Внедрение Polyspace

Эта проверка проверяет сравнение плавающей точки с операторами равенства.

Примеры

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

Проблема

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

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)

См. примеры исправлений ниже.

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

Пример - Плавает неравенство в for- петля
#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-loop проверяет неравенство 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);
}

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

Группа: Rec. 05. Плавающая точка (FLP)
Представлен в R2019a

[1] Данное программное обеспечение было создано компанией MathWorks и включает в себя следующие компоненты: «Веб-сайт SEI CERT-C», © 2017 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОНА И/ИЛИ ЕГО ПРОГРАММНОГО ИНЖЕНЕРНОГО ИНСТИТУТА, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ КАК ЕСТЬ. УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБЫХ ВОПРОСОВ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИИ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ ТОВАРНОЙ ПРИГОДНОСТИ, ИСКЛЮЧИТЕЛЬНОСТИ ИЛИ РЕЗУЛЬТАТОВ, ПОЛУЧЕННЫХ ОТ ИСПОЛЬЗОВАНИЯ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Данное программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллона или его Институтом разработки программного обеспечения.