Форматы float32 и double64 на пальцах
Вкратце, идея довольна простая: исходное число необходимо привести к нормализованному виду 1.NNN2
в двоичной системе счисления с помощью битового сдвига, затем записать дробную часть этого числа в мантиссу, а количество сдвигов в экспоненту. И завершающим штрихом сохранить знак исходного числа.
Формат float32 имеет такой вид: 1s8e23m
, где s — количество бит под знак, e — экспонента, m — мантисса. Для формата double64 вид такой — 1s11e52m
.
Первый бит кодирует знак числа. Если это ноль, число положительно, в противном случае число отрицательное.
Затем идут восемь бит экспоненты. Если совсем простыми словами, то экспонента — это количество сдвигов запятой в исходном числе, представленном в двоичном виде, для получения нормализованного числа вида 1.NNN2
. Чтобы получить количество сдвигов из этих восьми бит надо отнять 12710
. Отрицательная экспонента — сдвиг влево, положительная — сдвиг вправо.
После экспоненты следуют 23
бита мантиссы. Это дробная часть числа 1.NNN2
.
А теперь практическая часть!
Перевод десятичной дроби во float32
Попробуем с полученными знаниями закодировать число -2.62510
.
В двоичном виде это число имеет вид 10.1012
. Для получения нормализованного числа необходимо запятую сдвинуть влево на один разряд. Получим число 1.01012
и экспоненту равной 1
.
Для сохранения экспоненты к ней надо прибавить 12710
. Получится 12610
или 011111102
в двоичном виде.
Берем нормализованное число 1.01012
и выделяем мантиссу 01012
. Для сохранения этого числа, которое занимает 4 бита, надо добавить нули справа до 23 бит. Получится число 010100000000000000000002
.
Знак числа отрицательный, значит первый бит равен единице.
Итог: s=12
e=011111102
m=010100000000000000000002
, с чем я вас и поздравляю.
Обратный перевод: из float32 в число
Разберем пример из википедии. Есть число во float32 0xC000000016
. В двоичной системе это будет 110000000000000000000000000000002
.
Разобъем его на компоненты: s=12
e=100000002
m=000000000000000000000002
.
Мантисса равна нулю, но, как уже было сказано выше, сохраняется только дробная часть мантиссы, а единица отбрасывается. Значит мантисса равна 1.000000000000000000000002
.
Экспонента равна 100000002
или 12810
, отнимаем 12710
и получается, что экспонента равна единице.
Возьмем мантиссу и сдвинем точку вправо на эту единицу, получится 10.00000000000000000000002
, это 210
в десятичной системе счисления.
Знак числа равен единице, значит исходное число отрицательное.
Решение: -210
, что и требовалось доказать.
P.S. Маленькие циферки справа от числа обозначают систему счисления, если кто не знает. Пример: два в десятичной системе — 210, один‑ноль‑один в двоичной системе — 1012. Кстати, красным цветом выделен знак числа, зелёным — экспонента, а мантисса, соответственно, синим.
Полезные ссылки