exponenta event banner

CERT C: FLP36-C правил

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

Описание

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

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

Внедрение Polyspace

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

Примеры

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

Проблема

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

Например, long int стоимость 1234567890L слишком велик для переменной типа float .

Риск

Если тип с плавающей запятой не может представлять целое значение, поведение не определено (см. C11 standard, 6.3.1.4, para.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;
  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;
}

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

Группа: Правило 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 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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