Перейти к основному содержимому

Вещественные числа

Хранение чисел в памяти

Вещественные числа хранятся в памяти в следующем вид

  • S - знак мантиссы (0 - положительное число, 1 - отрицательное число)
  • E - порядок (выражает степень основания числа, на которое умножается мантисса)
  • M - мантисса (выражает значение числа без учёта порядка)

Вещественные числа хранятся в нормализованном виде и денормализованном виде (маленькие по модулю). Рассмотрим пример нормализации десятичного числа 123.45. Такое число представляется в виде:

123.45=1.2345102123.45 = 1.2345 * 10^2

Аналогично для двоичного числа - 1111.101 (15.62510):

1111.101=1.111101231111.101 = 1.111101 * 2^3

Размер выделенный под хранение вещественных чисел зависит от архитектуры ЭВМ. В языке Си определены типы

ТипРазмерМантисаПорядокСдвиг
float32238127
double6452111023
long double80641516383

Рассмотрим на примере как будет хранится число 15.625 в типе float. Для наглядности, используем функцию, которая отобразит наше число в двоичном виде.

#include <stdio.h>

void print_float_bin(float);

int main(void){
float f=15.625;
print_float_bin(f);
return 0;
}

void print_float_bin(float num) {
unsigned int* fi = (unsigned int*)&num;
for(int i=31;i>=0;i--) {
if(i==30 || i==22)
putchar(' ');
if(*fi&(1<<i))
putchar('1');
else
putchar('0');
}
putchar('\n');
}

В результате получим следующий вывод на консоль:

Вывод на консоль

Если число слишком мало (по модулю), оно представляется в денормализованном виде. Поле E заполняется нулями, порядок принимается равным 1-bias , а мантисса должна в этом случае принадлежать полуинтервалу [0.0, 1.0). В поле M пишется последовательность битов кодирующая дробную часть мантиссы (ведущий 0 отбрасывается).

Погрешность вещественных чисел

Xотя запись вещественных чисел и позволяет определить очень большой диапазон значений, но не все эти числа могут быть представлены с полной точностью. Числа с плавающей запятой в целом являются приблизительными представления точного числа. Например, число 1254311179 выглядело бы так: 1.254311E09. Однако если перейти к десятичной записи, то это будет 1254311000. А это не то же самое, что и 1254311179, поскольку мы потеряли три младших разряда.

Эту особенность следует учитывать при сравнении двух вещественных чисел.

Так не надо !!!
 float a,b;
scanf("%f%f",&a,&b);
if (a==b)
printf("Yes");
else
printf("No");
Используйте epsilon
float a,b;
scanf("%f%f",&a,&b);
if (fabs(a-b) < 0.0001)
printf("Yes");
else
printf("No");