Представление с плавающей точкой

Объясним представление с плавающей точкой (floating-point notation) на примере, в котором для хранения числа будем использовать только 1 байт памяти. Хотя в машинах обычно используются более длинные коды, этот 8-битовый формат является уменьшенным аналогом существующих систем, и позволяет объяснить основные понятия, не загромождая объяснение длинными последовательностями битов.

Прежде всего, назовем старший разряд бита знаковым разрядом. Как и раньше, 0 в позиции знакового разряда означает, что число неотрицательное, 1 в позиции знакового разряда означает, что число отрицательное. Затем разделим оставшиеся в байте семь разрядов на две группы или два поля: порядок (exponent field) и мантиссу (mantissa field). Пусть первые три бита после знакового будут порядком, а оставшиеся четыре — мантиссой (рис. 1.25).

Рассмотрим значение каждой из частей на следующем примере. Предположим, что байт содержит такую последовательность битов: 01101011. Проанализируем эту последовательность, применяя определения, данные выше: знаковый разряд равен 0, порядок — 110 и мантисса — 1011. Для того чтобы расшифровать значение, хранящееся в байте, сначала извлекаем мантиссу и помещаем слева от нее разделительную точку, получая.1011.

Затем извлекаем порядок (ПО) и переводим его как 3-битовое представление с избытком в десятичную систему счисления. В нашем случае код порядка является представлением 2. Перемещаем разделительную точку на 2 бита вправо (отрицательный порядок означает, что точку нужно перемещать влево). Следовательно, мы имеем последовательность

10.11,

которая является двоичной записью дроби 23/4. Затем обращаем внимание на то, что знаковый разряд равен 0, следовательно, перед нами неотрицательное число. Делаем вывод, что в байте 01101011 хранится число 23/4.

В качестве еще одного примера рассмотрим байт 10111100. Выписываем мантиссу

.1100

и перемещаем точку на один бит влево, так как порядок (011) является кодом числа — 1. Имеем последовательность.01100,

которая является кодом 3/8. Знаковый разряд исходной последовательности равен 1, значит, число отрицательное. Делаем вывод, что последовательность 10111100 является кодом -3/8.

Чтобы записать число в представлении с плавающей запятой, выполняем действия, обратные предыдущим. Например, чтобы записать число 1'/8, сначала выражаем его в двоичном представлении и получаем 1.001. Затем переписываем эту последовательность в область мантиссы слева направо, начиная с самой левой единицы в двоичной записи. На этом этапе байт выглядит следующим образом: ______I00L

Теперь нужно заполнить поле порядка. Для этого представляем мантиссу с разделительной точкой слева и определяем число битов и направление, в котором нужно передвинуть точку, чтобы получить исходную двоичную запись. В нашем примере, чтобы получить 1.011, нужно передвинуть точку в.1001 на один бит вправо. Следовательно, порядок равен 1, поэтому записываем 101 (код 1 в представлении с избытком 4) в поле порядка. Наконец, записываем в позицию знакового разряда 0, потому что дробь неотрицательная. Окончательный байт выглядит так:

Q101100I.

Наиболее тонким моментом в преобразовании является заполнение поля мантиссы. Правило гласит: выписывать последовательность разрядов двоичной записи слева направо, начиная с самой левой 1 в двоичной записи. В качестве примера рассмотрим процесс записи числа 3/8, двоичное представление которого.011. В этом случае мантиссой будет

______110 й,

а не

___оно.

Мантисса имеет такой вид, потому что поле мантиссы заполняется, начиная с самой левой единицы, которая появляется в двоичном представлении. Это правило исключает возможность многократной записи одного значения. Оно также означает, что мантисса чисел, не равных нулю, будет всегда начинаться с 1. О таком представлении говорят, что оно нормализованное (normalized form). Обратите внимание, что представление нуля является особым случаем: его представление с плавающей точкой состоит из одних нулей.

Ошибка усечения

Рассмотрим проблему, которая возникает, когда мы пытаемся записать значение 25/8 в представлении с плавающей точкой, используя для него один байт памяти. Сначала записываем 25/8 в двоичном представлении, получаем 10.101. Но, когда мы переписываем его в поле мантиссы, нам не хватает места, и самая правая 1 (которая занимает позицию с весом разряда '/8) теряется (рис. 1.26). Если мы на данном этапе будем игнорировать эту проблему и продолжим заполнение поля порядка, то в результате придем к последовательности 01101010, которая является представлением 2'/2 вместо 25/8. То, что произошло, называется ошибкой усечения (truncation error), или ошибкой округления (round-off error), и означает, что часть числа потеряна, потому что поле мантиссы недостаточно велико.

Количество таких ошибок можно уменьшить, если использовать более длинное поле для мантиссы. Как и в случае с целыми числами, для хранения чисел в форме представления с плавающей точкой принято использовать по меньшей мере 32 бита вместо 8 битов, которые мы использовали здесь. Такой подход позволяет также увеличить поле для порядка числа. Но даже в этом формате представления иногда возникает необходимость более точных расчетов.

Другой причиной ошибки усечения может быть явление, с которым вы уже сталкивались в десятичной системе счисления: проблема бесконечных дробей, таких, например, которые появляются, когда мы пытаемся представить '/3 в виДе десятичной дроби. Некоторые числа просто нельзя точно записать в виде десятичной дроби, независимо от количества цифр, которое мы используем.

Десятичная и двоичная системы счисления различаются тем, что в двоичной системе существует больше чисел с бесконечным представлением, чем в десятичной. Например, дробь '/,„ является бесконечной в двоичном представлении. Вообразите, какие проблемы это повлечет за собой, если неосмотрительный пользователь будет использовать представление с плавающей точкой для того, чтобы хранить и производить операции с деньгами. В особенности, если в качестве единицы измерения он будет использовать доллар, то значение в десять центов будет записано неточно. В этом случае лучше выбрать единицей хранения данных 1 цент так, чтобы все значения были целыми и могли быть с достаточной точностью представлены в памяти компьютера при помощи двоичного дополнительного кода.

Ошибка усечения и связанные с нею проблемы представляют большую важность для людей, работающих в области численного анализа. Этот раздел математики занимается проблемами, которые возникают при действительных расчетах, часто очень объемных и требующих высокой точности.

Следующий пример придется по сердцу любому специалисту в области численного анализа. Предположим, нам нужно найти сумму следующих трех чисел, используя 1 байтовое представление с плавающей точкой:

01/ + 1/ + 1/ с. / 2 '8 '8-

Если мы будем складывать числа в указанном порядке, то сначала прибавим 78 к 21/2, получим дробь 25/8, двоичная запись которой — 10.101. К сожалению, когда мы сохраняем это число, возникает ошибка усечения, в результате которой полученная нами сумма будет сохранена как 272 (что равно одному из слагаемых). На следующем шаге мы прибавляем к этой сумме 78. Здесь опять возникает ошибка усечения, в результате которой мы получаем неправильный ответ 272.

Теперь сложим эти числа в другом порядке. Сначала найдем сумму '/8 и '/8, которая равна '/4. В двоичном представлении '/4 равна.01. Результат первого шага будет храниться в байте 00111000, что верно. Теперь находим сумму '/4 и следующего числа 272, получаем значение 23/4, которое хранится в байте 01101011. На этот раз мы получили правильный ответ.

Следовательно, при сложении числовых значений важен порядок их сложения. Проблема состоит в том, что при сложении большого и маленького числа, маленькое число может отсекаться. Поэтому общее правило сложения чисел звучит следующим образом: сначала складываем небольшие числа, надеясь, что в сумме они дадут число, которое можно сложить с большим. Именно это явление было описано в предыдущем примере.

Разработчики современного коммерческого программного обеспечения защищают неграмотного пользователя от таких проблем, как эта. В обычных программах табличных вычислений пользователь получит правильный ответ, если только слагаемые не различаются в 106 раз. Следовательно, если вам нужно прибавить единицу к 10 00О 000 000 000 000, вы получите 10 000 000 000 000 000, а не 10 000 000 000 000 001.

Проблема сложения важна в прикладных системах (таких как навигационное устройство), так как незначительная ошибка может увеличиться в процессе дальнейших вычислений и, в конце концов, привести к серьезным последствиям, но для обычных пользователей ПК такой точности вполне достаточно.

Сжатие данных

Для того чтобы хранить и передавать данные, часто полезно (а иногда даже необходимо) сократить размер этих данных. Метод, который используется для этого, называется сжатием данных (data compression). В начале этого раздела мы рассмотрим некоторые общие методы сжатия данных, а затем познакомимся с некоторыми техниками, предназначенными специально для сжатия изображений.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: