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

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

Описание

Управляйте определением

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

Примеры

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

Описание

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

Например, значение 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;
 }

Некоторые реализации обеспечивают встроенную функцию, чтобы определить точность целого числа. Например, 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 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

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

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