Precision loss in integer to float conversion

Младшие значащие биты целого числа, потерянного во время преобразования в тип с плавающей точкой

Описание

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

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

Информация о результате

Группа: числовой
Язык: C | C++
Значение по умолчанию: Off
Синтаксис командной строки: INT_TO_FLOAT_PRECISION_LOSS
Удар: низко
ID CWE: 189, 681, 704
Введенный в R2018b