Кодирование вещественных чисел
Несколько иной способ применяется для представления в памяти персонального компьютера действительных чисел. Рассмотрим представление величин с плавающей точкой.
Любое действительное число можно записать в стандартном виде M × 10p, где 1 £ M < 10, p — целое. Например, 120100000 = 1,201 × 108. Поскольку каждая позиция десятичного числа отличается от соседней на степень числа 10, умножение на 10 эквивалентно сдвигу десятичной запятой на одну позицию вправо. Аналогично деление на 10 сдвигает десятичную запятую на позицию влево. Поэтому приведенный выше пример можно продолжить: 120100000 = 1,201 × 108 = 0,1201 × 109 = 12,01 × 107. Десятичная запятая "плавает" в числе и больше не помечает абсолютное место между целой и дробной частями.
В приведенной выше записи M называют мантиссой числа, а p — его порядком. Для того чтобы сохранить максимальную точность, вычислительные машины почти всегда хранят мантиссу в нормализованном виде, что означает, что мантисса в данном случае есть число, лежащее между 1(10) и 2(10) (1 £ M < 2). Основание системы счисления здесь, как уже отмечалось выше, — число 2. Способ хранения мантиссы с плавающей точкой подразумевает, что двоичная запятая находится на фиксированном месте. Фактически подразумевается, что двоичная запятая следует после первой двоичной цифры, т.е. нормализация мантиссы делает единичным первый бит, помещая тем самым значение между единицей и двойкой. Место, отводимое для числа с плавающей точкой, делится на два поля. Одно поле содержит знак и значение мантиссы, а другое содержит знак и значение порядка.
Современный персональный компьютер позволяет работать со следующими действительными типами (диапазон значений указан по абсолютной величине; в некоторых случаях перечень типов данных может быть расширен):
Тип | Диапазон | Мантисса | Байты |
Real | 2,9×10-39..1,7×1038 | 11-12 | |
Single | 1,5×10-45..3,4×1038 | 7-8 | |
Double | 5,0×10-324..1,7×10308 | 15-16 | |
Extended | 3,4×10-4932..1,1×104932 | 19-20 |
Покажем преобразование действительного числа для представления его в памяти ЭВМ на примере величины типа Double.
Как видно из таблицы, величина это типа занимает в памяти 8 байт. На рисунке ниже показано, как здесь представлены поля мантиссы и порядка (нумерация битов осуществляется справа налево):
S | Смещенный порядок | Мантисса |
62..52 | 51..0 |
Можно заметить, что старший бит, отведенный под мантиссу, имеет номер 51, т.е. мантисса занимает младшие 52 бита. Черта указывает здесь на положение двоичной запятой. Перед запятой должен стоять бит целой части мантиссы, но поскольку она всегда равна 1, здесь данный бит не требуется и соответствующий разряд отсутствует в памяти (но он подразумевается). Значение порядка хранится здесь не как целое число, представленное в дополнительном коде. Для упрощения вычислений и сравнения действительных чисел значение порядка в ЭВМ хранится в виде смещенного числа, т.е. к настоящему значению порядка перед записью его в память прибавляется смещение. Смещение выбирается так, чтобы минимальному значению порядка соответствовал нуль. Например, для типа Double порядок занимает 11 бит и имеет диапазон от 2-1023 до 21023, поэтому смещение равно 1023(10) = 1111111111(2). Наконец, бит с номером 63 указывает на знак числа.
Таким образом, из вышесказанного вытекает следующий алгоритм для получения представления действительного числа в памяти ЭВМ:
1. перевести модуль данного числа в двоичную систему счисления;
2. нормализовать двоичное число, т.е. записать в виде M × 2p, где M — мантисса (ее целая часть равна 1(2)) и p — порядок, записанный в десятичной системе счисления;
3. прибавить к порядку смещение и перевести смещенный порядок в двоичную систему счисления;
4. учитывая знак заданного числа (0 — положительное; 1 — отрицательное), выписать его представление в памяти ЭВМ.
Пример. Запишем код числа -312,3125.
1. Двоичная запись модуля этого числа имеет вид 100111000,0101.
2. Имеем 100111000,0101 = 1,001110000101 × 28.
3. Получаем смещенный порядок 8 + 1023 = 1031. Далее имеем 1031(10) = 10000000111(2).
4. Окончательно
62..52 | 51..0 |
Очевидно, что более компактно полученный код стоит записать следующим образом: C073850000000000(16).
Другой пример иллюстрирует обратный переход от кода действительного числа к самому числу.
Пример. Пусть дан код 3FEC600000000000(16) или
62..52 | 51..0 |
1. Прежде всего замечаем, что это код положительного числа, поскольку в разряде с номером 63 записан нуль. Получим порядок этого числа: 01111111110(2) = 1022(10); 1022 - 1023 = -1.
2. Число имеет вид 1,1100011 × 2-1 или 0,11100011.
3. Переводом в десятичную систему счисления получаем 0,88671875.