В отличие от методов представления целых чисел, задача представления числовых значений с дробной частью требует не только сохранения комбинаций из нулей и единиц, образующих его двоичное представление, но и запоминания позиции точки, отделяющей целую часть от дробной.
Двоичная нотация с плавающей точкой.
Преимущество использования представления чисел в формате с плавающей запятой над представлением в формате с фиксированной запятой (и целыми числами) состоит в том, что можно использовать существенно больший диапазон значений при неизменной относительной точности. Например, в форме с фиксированной запятой число, занимающее 8 разрядов в целой части и 2 разряда после запятой, может быть представлено в виде 123456,78; 8765,43; 123,00 и так далее. В свою очередь, в формате с плавающей запятой (в тех же 8 разрядах) можно записать числа 1,2345678; 1234567,8; 0,000012345678; 12345678000000000 и так далее, но для этого необходимо двухразрядное дополнительное поле для записи показателей степени 10 от 0 до 1610, при этом общее число разрядов составит 8+2=10.
Число с плавающей запятой состоит из: * Мантиссы (выражающей значение числа без учёта порядка) * Знака мантиссы (указывающего на отрицательность или положительность числа) * Порядка (выражающего степень основания числа, на которое умножается мантисса) * Знака порядка
Первый (старший) бит в такой нотации является знаковым (если 0 – число неотрицательное; если 1 – отрицательное). Оставшиеся биты разделены на две группы: поле порядка числа и поле мантиссы. Например, для однобайтового представления числа выберем следующие числа бит (см. рис. 18).
Рис. 18.Представление числа с плавающей точкой при использовании восьми разрядов.
Алгоритм декодирования двоичной нотации с плавающей точкой имеет следующий вид (с учетом рис. 19).
А1:При разложении этой комбинации определим, что знаковый бит равен 0, поле порядка имеет значение 110, а поле мантиссы – значение 1011;
А2:Выделим мантиссу и поместим точку слева от нее, т.е. .1011;
А3:Выделим значение поля порядка числа (110) и интерпретируем его как целое трехразрядное число, записанное в двоичной нотации с избытком (это число 2, см. рис. 19). Это означает, что плавающую точку в полученном ранее значении следует переместить на два бита вправо, после чего будет получен окончательный результат: 10.11; Это значение является двоичным представлением числа 2 ¾ т.к.: 10.11 (2) = 1⋅21 + 0⋅20 + 1⋅2-1 + 1⋅2-2 = 2,75 (10)
Отметим также, что для представления действительных чисел типа Real в языке Pascal реально используется шесть байт, а диапазон таких чисел 2.9e-39..1.7e38, с использованием знака.
Рис. 19.Двоичная нотация с избытком при использовании трехбитного представления.
Ошибки усечения данных. Рассмотрим одну неприятную проблему, которая возникает при попытке представить число 2 5/8 в виде однобайтового кода в двоичной нотации с плавающей точкой. Двоичное представление числа 2 5/8 будет 10.101 (2) = 1⋅21 + 0⋅20 + 1⋅2-1 + 0⋅2-2 + 1⋅2-3. В поле мантиссы имеющихся четырех разрядов будет недостаточно и младший бит мантиссы, имеющий весовое значение 1/8 теряется (см. рис. 20).
Если на это не обратить внимание, то будет получена комбинация 01101010, которая на самом деле представляет число 2 ½, а не 2 5/8. Это явление называется ошибкой усечения. Во избежание подобных ошибок обычно используют поле мантиссы большего размера. Но даже при 32-х битном представлении ошибка усечения данных имеет место, а точность представления числовых значений иногда оказывается недостаточной.
Рис. 20.Возникновение ошибки усечения данных.
Интересно отметить, что с учетом усечения разной будут суммы:2 ½ + 1/8 + 1/8 = 2 ½ (неверный ответ) и 1/8 + 1/8 + 2 ½ = 2 ¾ (правильный ответ). Таким образом, при сложении чисел большое значение имеет порядок, в котором они суммируются. Общее правило суммирования большого количества чисел требует начинать операцию сложения с самых малых чисел, предполагая, что в результате будет получено достаточно большое промежуточное значение, которое затем можно безопасно сложить с оставшимися большими числами.