Чтобы было проще, начнём с обычного десятичного числа
35.42, у которого, как можно видеть, имеется дробная часть. Как ещё можно записать это число? Ну, к примеру, вот так:3 * (10 ** 1) + 5 * (10 ** 0) + 4 * (10 ** -1) + 2 * (10 ** -2)
То есть тут повторяется ситуация с порядковыми номерами, которую мы видели ранее при обсуждении целых чисел. Каждая цифра здесь привносит определённое значение в зависимости от своего порядкового номера.
При этом цифрам, стоящим после точки, мы просто присваиваем отрицательные индексы. В принципе, это же число можно представить как
35 + (42 / 100), суть та же.Ясное дело, этот принцип можно применить и двоичным числам. К примеру, если взять двоичное
101.11, то у нас выйдет:1 * (2 ** 2) + 0 * (2 ** 1) + 1 * (2 ** 0) + 1 * (2 ** -1) + 1 * (2 ** -2)
Или, проще говоря,
4 + 0 + 1 + (1/2) + (1/4)
То есть мы видим, что после точки у нас появляются дроби со степенями двойки:
1/2, 1/4, 1/8, и так далее. Так мы можем легко представить дробь 3/16 (или 0.1875), это будет 0.0011. Хотя такой подход в теории можно использовать, он не слишком удобен, особенно для очень больших чисел.Поэтому стандарт IEEE 754 представляет дробные числа в виде формулы:
((-1) ** s) * M * (2 ** E)
Здесь три параметра, и в компьютере каждый хранится в своём поле.
s равно либо 0, либо 1. Это информация о знаке, соответствующее поле занимает всегда 1 бит.M - это мантисса, дробное число, обычно меньше 1. Его представляет поле frac, занимает оно n бит и содержит последовательность`f(n-1), ..., f(1), f(0)`.Ну, а
E - это экспонента, которая может быть как положительной, так и отрицательной. Её представляет поле exp длиной k бит с последовательностью e(k-1), ..., e(1), e(0).Итак, эти числа состоят аж из трёх полей сразу, и обычно имеют либо одинарную (single, 32 бита), либо двойную (double, 64 бита) точность. К примеру, для одинарной точности
s занимает один бит номер 31, exp - с 23 по 30 биты, остальное (с 0 по 22) отводится под мантиссу.Здесь, правда, возможно три разных случая.
Первый случай самый типичный, он описывает нормированные значения. Это случай, когда экспонента не состоит целиком из нулей или целиком из единиц. Говорят, что экспонента хранится в смещённой (biased) форме, а само её значение считается как:
E = e - B
e - число без знака с последовательностью
e(k-1), ..., e(1), e(0). B - это значение bias, которое равно 2 ** (k - 1) - 1, то есть для одинарной точности оно равно 127, потому что в этом случае длина поля exp составляет 8 бит.Следовательно, финальное значение
E будет лежать в пределах от -126 (тк e - число без знака, и оно точно больше нуля в данном случае) до 127 для одинарной точности.Поле
frac в этом случае описывает дробную часть, то есть его значение f в десятичном виде лежит от 0 (включительно) до 1 (не включительно), это довольно важно, процесс формирования f увидим в примере ниже. Финальное значение мантиссы M = 1 + f. Следующий случай - денормированные значения, это когда в поле
exp содержатся все нули. В этом случае E = 1 - B, M = f.Такие денормированные значения, в частности, используются, чтобы представить значение 0. А чего бы нам для нуля не использовать первый случай? Ну потому, что там
M = 1 + f, то есть в любом случае M >= 1.Кстати, тут получается интересный момент: у нас может быть как +0, так и -0. Почему? Потому что хотя биты в
exp и frac занулены, s всё равно может иметь значение как 0, так и 1.На самом деле, этот случай используется ещё и тогда, когда нужно представить числа, очень близкие к нулю, как мы увидим в примере ниже.
Последний третий случай - это специальные значения, когда в поле
exp записаны все единицы. Правда, этот случай содержит два других возможных сценария.Если в
frac записаны одни нули, то таким образом мы представляем бесконечность (плюс или минус бесконечность, зависит от знака s) - примеру, если мы поделили на ноль.