Вещественные числа
Хранение чисел в памяти
Вещественные числа хранятся в памяти в следующем вид
- S - знак мантиссы (0 - положительное число, 1 - отрицательное число)
- E - порядок (выражает степень основания числа, на которое умножается мантисса)
- M - мантисса (выражает значение числа без учёта порядка)
Вещественные числа хранятся в нормализованном виде и денормализованном виде (маленькие по модулю). Рассмотрим пример нормализации десятичного числа 123.45. Такое число представляется в виде:
Аналогично для двоичного числа - 1111.101 (15.62510):
Размер выделенный под хранение вещественных чисел зависит от архитектуры ЭВМ. В языке Си определены типы
Тип | Размер | Мантиса | Порядок | Сдвиг |
---|---|---|---|---|
float | 32 | 23 | 8 | 127 |
double | 64 | 52 | 11 | 1023 |
long double | 80 | 64 | 15 | 16383 |
Рассмотрим на примере как будет хранится число 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*)#
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");
float a,b;
scanf("%f%f",&a,&b);
if (fabs(a-b) < 0.0001)
printf("Yes");
else
printf("No");