CERT C++: FLP36-C

Сохраните точность при преобразовании интегральных значений в тип с плавающей точкой

Описание

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

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

Реализация Polyspace

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

Примеры

расширить все

Проблема

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

Для образца, long int значение 1234567890L слишком велик для переменной типа float .

Риск

Если тип с плавающей точкой не может представлять целое значение, поведение не определено (см. C11 стандарт, 6.3.1.4, абзац 2). Для образца можно отбросить наименее значимые биты значения переменных, что приведет к неожиданным результатам.

Зафиксировать

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

Для образца, если float тип данных не может представлять целое значение, используйте double вместо этого тип данных.

При записи функции, которая преобразует целое число в тип с плавающей точкой, перед преобразованием проверьте, может ли целое значение быть представлено в типе с плавающей точкой. Для образца, DBL_MANT_DIG * log2(FLT_RADIX) представляет количество основы -2 цифр в типе double. Перед преобразованием в тип double, проверьте, больше ли это число или равно точности целого числа, которое вы преобразуете. Чтобы определить точность целого числа num, используйте этот код:

 size_t precision = 0;
 while (num != 0) {
    if (num % 2 == 1) {
      precision++;
    }
    num >>= 1;
 }

Некоторые реализации обеспечивают функцию builtin, чтобы определить точность целого числа. Для образца GCC обеспечивает функцию __builtin_popcount.

Пример - Преобразование большого целого числа в тип с плавающей точкой
#include <stdio.h>

int main(void) {
  long int big = 1234567890L;
  float approx = big;//Noncompliant
  printf("%ld\n", (big - (long int)approx));
  return 0;
}

В этом примере long int переменная big преобразуется в float.

Коррекция - используйте более широкий тип с плавающей точкой

Одной из возможных коррекций является преобразование в double тип данных вместо float.

#include <stdio.h>

int main(void) {
  long int big = 1234567890L;
  double approx = big;
  printf("%ld\n", (big - (long int)approx));
  return 0;
}

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

Группа: 49. Разное (MSC)
Введенный в R2019a

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

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

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