Электронный учебник

§ 27. Хранение в памяти целых чисел

 

Целые числа без знака
Беззнаковые (англ. unsigned) типы данных, т. е. величины, не имеющие отрицательных значений, широко используются в вычислительной технике. Дело в том, что в задачах, решаемых на компьютерах, есть много таких значений: всевозможные счётчики (количество повторений циклов, число параметров в списке или символов в тексте), количество людей или предметов и др.
Чтобы закодировать целое число без знака, достаточно перевести его в двоичную систему счисления (см. § 11) и дополнить слева нулями до нужной разрядности. Например, число 28 записывается в 8-разрядную ячейку памяти так:
                                                                                                   0001 1100
Это же число в 16-разрядном представлении будет иметь слева ещё 8 нулей. Восьмиразрядные коды некоторых характерных чи¬сел приведены в табл. 4.1.
Минимальное значение для беззнаковых целых чисел всегда равно 0 (все разряды нулевые), а максимальное число Хmax =2K -1 СОСТОИТ из всех единиц и определяется разрядностью (количеством битовколичеством битов) К (табл. 4.2).
 
Возникает вопрос: что будет, если увеличить максимальное число в К-битной ячейке на единицу? Рассмотрим случай К =8 и попытаемся прибавить еденицу  к числу 25510 = 1111 11112. Добавляя дополнительный бит слева, получим: 
 
Отбросив несуществующий дополнительный разряд1, получаем 255 + 1 = 0. Как ни странно, именно это произойдёт в реальном компьютере. Говорят, что при К разрядах арифметика выполняется по модулю 2К, т. е. при К = 8 имеем2:
                                 (255 + 1) mod 256 » 256 mod 256 = 0.
 
 
1 На самом деле, для того чтобы обнаружить факт переполнения, этот  разряд сохраняется в специальном ynpaвляющем бите процессора, который называется битом переноса.
2 Здесь запись a mod b обозначает остаток от деления а на b.
 
Вместе с тем, вычитая единицу из минимального значения О, к которому добавлен старший разряд за пределами 8-битной ячейки, получим 1111 11112 = 25510 (проверьте это самостоятельно).
Можно заметить, что при многократном увеличении числа на единицу мы доходим до максимального значения и скачком возвращаемся к минимальному. При вычитании единицы получается обратная картина — дойдя до минимума (нуля), мы сразу перескакиваем на максимум (255). Поэтому для изображения допустимого диапазона чисел лучше подходит не отрезок числовой оси (как в математике), а окружность (рис. 4.6).
Факт переполнения всегда фиксируется процессором, но выполнение программы не прерывается. Программе (точнее, программисту) предоставляется возможность как-то реагировать на переполнение или «не заметить* его.
 
Целые числа со знаком
Теперь рассмотрим числа со знаком (англ. signed). Для того чтобы различать положительные и отрицательные числа, в двоич¬ном коде выделяется один бит для хранения знака числа — знаковый разряд. По традиции для этого используют самый старший бит, причём нулевое значение в нём соответствует знаку «плюс», а единичное — знаку «минус». Ноль формально является положительным числом, так как все его разряды, включая знаковый, нулевые.
Поскольку один бит выделяется для хранения информации о знаке, ровно половина из всех 2К чисел будут отрицательными. Учитывая, что одно значение — нулевое, положительных чисел будет на единицу меньше, т. е. допустимый диапазон значений оказывается несимметричным.
Положительные числа записываются в знаковой форме так же, как и в беззнаковой, но для значения остаётся на один разряд меньше. А как поступить с отрицательными числами? Первое, что приходит в голову, это кодировать отрицательные значения точно так же, как и положительные, только записывать в старший бит единицу. Такой способ кодирования называется прямым кодом. Несмотря на свою простоту и наглядность, он не применяется в компьютерах для представления целых чисел1. Это неудобно, потому что действия над числами, записанными в прямом коде, выполняются по-разному для разных сочетаний знаков чисел. Поэтому в современных компьютерах отрицательные числа кодируются с помощью другого метода, который менее нагляден, но позволяет выполнять арифметические действия с положительными и отрицательными числами по одному и тому же алгоритму.
Как же представить целые числа, чтобы арифметика выглядела максимально просто? Попробуем, например, вычислить код, соответствующий числу —1. Для этого просто вычтем из нуля единицу:
 
 
 
Чтобы вычитание «состоялось», придется занять из несуществующего старшего бита единицу, что не очень естественно, но зато быстро приводит к правильному результату2. Заметим, что фактически мы вычитали не из 0, а из 256. В общем случае вычисление происходит по формуле 2К - X, где для данного примера К=8, а Х=1
 
1Тем не менее прямой код используется в представлении вех
2Для проверки можно прибавить к полученному коду единицу в  результате должен получиться ноль.
 
Однако предложенный способ перевода не слишком хорош, поскольку мы использовали дополнительный «несуществующий» разряд. Вместо этого можно использовать равносильный алгоритм:
                                                                        256 - X = (255 - X) + 1 = not X + 1.
Здесь «not» обозначает логическую операцию «НЕ» (инверсию), применяемую к каждому биту числа отдельно (все нули заменяются на единицы и
наоборот).
Итак, для получения кода целого числа (-Х) нужно:
 
Алгоритм А1
1) Выполнить инверсию каждого разряда двоичного
представления числа X (такой код называется обратным).
2) К полученному результату прибавить единицу.
 
В результате получается дополнительный код — он дополняет число до 2К.
Алгоритм А1 приводится в большинстве учебников, но его можно немного изменить так, чтобы облегчить человеку «ручные» вычисления:
 
Алгоритм А2
1) Вычислить число Х-1 и перевести его в двоичную систему.
2) Выполнить инверсию каждого разряда результата.
 
Оба алгоритма дают одинаковые результаты, но алгоритм А2 для человека существенно проще, потому что ему легче вычесть единицу в «родной» десятичной системе, чем прибавлять её в двоичной (при использовании алгоритма А1).
Наконец, оба пункта алгоритма А1 можно объединить, получив ещё один вариант:
 
Алгоритм A3
Выполнить инверсию всех старших битов числа, кроме последней (младшей) единицы и тех нулей, которые стоят после неё.
 
Например, определим дополнительный код числа «-16», которое хранится в 8-разрядной ячейке. Здесь X =16 - Используя алгоритмы А1 и А2, получаем:
Применение алгоритма A3 к числу 16 = 00010000сводится к замене первых трёх нулей единицами: 1111 00002.
Для проверки можно сложить полученный результат с исходным числом и убедиться, что сумма обратится в ноль (перенос из старшего разряда не учитываем).
Повторное применение любого из алгоритмов А1-АЗ всегда приводит к восстановлению первоначального числа (убедитесь в этом самостоятельно). Это свойство также удобно использовать для проверки.
В таблице 4.3 показаны шестнадцатеричные и двоичные коды некоторых характерных 8-разрядных чисел.
 
Обратите внимание на скачок при переходе от -1 к 0 и на два граничных значения: 127 и «-128». «Кольцо» для чисел со знаком выглядит так, как показано на рис. 4.7.
Чтобы сравнить коды целых чисел без знака и со знаком, объединим обе таблицы {4.1 и 4.3) — получим табл. 4.4.
Общее количество значений со знаком и без знака одинаково, но их диапазоны сдвинуты друг относительно друга на числовой оси (рис. 4,8).
В наших рассуждениях использовались 8-разрядные числа, но все выводы справедливы для чисел любой разрядности. От числа разрядов К зависят только граничные значения Хmax и Xmin, приведённые в табл. 4.5.
 
ХОТЯ дополнительный код гораздо менее нагляден, чем пря¬мой, он значительно упрощает выполнение арифметических опе¬раций в компьютере. Например, вместо вычитания используется сложение с дополнительным кодом вычитаемого, поэтому не нужно проектировать специальное устройство для вычитания чисел.
 
Вопросы и задания
1. Чем отличается представление в компьютере целых чисел со знаком
и без знака?
2. Приведите примеры величин, которые всегда имеют целые неотрицательные значения.
3. Как представлены в компьютере целые числа без знака?
4. Как изменится диапазон
представления чисел, если увеличить количество разрядов на 1? На 2? На п?
5. Какое максимальное целое беззнаковое число можно записать с помощью К двоичных разрядов? Что произойдёт, если прибавить единицу к этому максимальному значению?
6. Как действует процессор при переполнении?
7. Почему максимальное положительное и минимальное отрицательное значения у целых двоичных чисел со знаком имеют разные абсолютные значения?
8. Верно ли, что положительные числа кодируются одинаково в знаковом и беззнаковом форматах?
9. Сформулируйте различные алгоритмы получения дополнительного
кода для отрицательного числа.
*10. Докажите, что алгоритмы Al, A2 и A3 всегда дают один и тот же
результат.
11. Какое минимальное отрицательное значение можно записать с помощью К двоичных разрядов?
*12. Может ли быть переполнение при сложении двух отрицательных чисел? Какой знак будет у результата?
13. Что получится, если правила перевода в дополнительный код применить к отрицательному числу?
14.  Как можно проверить правильность перевода в дополнительный
код?
15.  В чём главное преимущество дополнительного кода при кодировании отрицательных чисел?
16.  Почему компьютер может обойтись без вычитания?
 
Подготовьте сообщение
а) «Способы кодирования отрицательных целых чисел»
б) «Целочисленные типы данных в языках программирования»

Block title

Вход на сайт

Поиск

Календарь

«  Май 2024  »
ПнВтСрЧтПтСбВс
  12345
6789101112
13141516171819
20212223242526
2728293031

Архив записей

Статистика


Онлайн всего: 1
Гостей: 1
Пользователей: 0