Десятичная точка явно нигде не хранится; это проблема отображения.
Следующее объяснение является упрощением; Я опускаю много важных деталей, и мои примеры не предназначены для представления какой-либо реальной платформы. Он должен дать вам представление о том, как значения с плавающей точкой представлены в памяти, и о проблемах, связанных с ними, но вы захотите найти более авторитетные источники, например, что каждый компьютерный специалист должен знать об арифметике с плавающей точкой .
Начните с представления значения с плавающей запятой в варианте научной нотации, используя базу 2 вместо базы 10. Например, значение 3.14159 можно представить как
0,7853975 * 2 2
0.7853975 - это значение , aka мантисса; это часть номера, содержащая значащие цифры. Это значение умножается на основание 2, возведенное в степень 2, чтобы получить 3,14159.
Числа с плавающей запятой кодируются путем хранения значений и экспоненты (вместе со знаковым битом).
Типичная 32-битная компоновка выглядит примерно так:
3 32222222 22211111111110000000000
1 09876543 21098765432109876543210
+-+--------+-----------------------+
| | | |
+-+--------+-----------------------+
^ ^ ^
| | |
| | +-- significand
| |
| +------------------- exponent
|
+------------------------ sign bit
Как и целочисленные типы со знаком, старший бит указывает знак; 0 обозначает положительное значение, 1 обозначает отрицательное.
Следующие 8 бит используются для показателя степени. Экспоненты могут быть положительными или отрицательными, но вместо резервирования другого знакового бита они кодируются так, что 10000000 представляет 0, поэтому 00000000 представляет -128, а 11111111 представляет 127.
Остальные биты используются для значимости. Каждый бит представляет отрицательную степень 2, считая слева, поэтому:
01101 = 0 * 2 -1 + 1 * 2 -2 + 1 * 2 -3 + 0 * 2 -4 + 1 * 2 -5
= 0,25 + 0,125 + 0,03125
= 0,40625
Некоторые платформы принимают «скрытый» ведущий бит в значении, который всегда равен 1, поэтому значения в значении и всегда находятся между [0,5, 1). Это позволяет этим платформам хранить значения с немного большей точностью (подробнее об этом ниже). Мой пример не делает этого.
Таким образом, наше значение 3.14159 будет представлено как что-то вроде
0 10000010 11001001000011111100111
^ ^ ^
| | |
| | + --- значимое = 0,7853975 ...
| |
| + ------------------- экспонента = 2 (130 - 128)
|
+ ------------------------- знак = 0 (положительный)
значение = -1 (знак) * 2 (показатель степени) * (значение и)
значение = -1 0 * 2 2 * 0,7853975 ...
значение = 3.14159 ...
Теперь, что вы заметите, если сложите все биты в значении и что они не составляют 0,7853975; они на самом деле выходят до 0,78539747. Недостаточно битов для точного хранения значения ; мы можем хранить только приближение. Количество бит в значении и определяет точность или сколько значащих цифр вы можете сохранить. 23 бита дают нам примерно 6 десятичных цифр точности. 64-битные типы с плавающей запятой предлагают достаточное количество бит в значении и дают примерно 12-15 цифр точности. Но имейте в виду, что есть значения, которые не могут быть представлены точно, независимо от того, какмного битов вы используете. Так же, как значения, такие как 1/3, не могут быть представлены конечным числом десятичных цифр, значения, подобные 1/10, не могут быть представлены конечным числом битов. Поскольку значения являются приблизительными, вычисления с ними также являются приблизительными, и ошибки округления накапливаются.
Количество бит в показателе степени определяет диапазон (минимальное и максимальное значения, которые вы можете представить). Но по мере продвижения к вашим минимальным и максимальным значениям размер разрыва между представленными значениями увеличивается. То есть, если вы не можете точно представить значения между 0,785397 и 0,785398, то вы не можете точно представить значения между 7,85397 и 7,85398, либо значения от 78,5397 до 78,5398, либо значения между 785397.0 и 785398.0. Будьте осторожны при умножении очень больших (по величине) чисел на очень маленькие числа.