3.1.1. Аппаратное представление целых чисел

3.1.1. Аппаратное представление целых чисел

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

Примечание

Такая реализация целых чисел может также приводить к проблемам при переносе языка на другую аппаратную платформу, но для Delphi это, видимо, не очень актуально.

Целые числа могут быть знаковыми и беззнаковыми. Сначала рассмотрим формат более простых беззнаковых чисел. Если у нас есть N двоичных разрядов для хранения такого числа, то мы можем представить любое число от 0 до 2N-1. В Delphi беззнаковые целые представлены фундаментальными типами Byte (N=8, диапазон 0..255), Word (N=16, диапазон 0..65 535) и LongWord (N=32, диапазон 0..4 294 967 295).

Примечание

Фундаментальными называются те типы данных, разрядность которых не зависит от аппаратной платформы. Кроме них существуют еще общие (generic) типы, разрядность которых определяется разрядностью платформы. В Delphi это типы Integer (знаковое целое) и Cardinal (беззнаковое целое. В имеющейся реализации они имеют 32 разряда, но при переходе на 64-разрядные компиляторы следует ожидать что эти типы также станут 64-разрядными. В частности, в 16-разрядном Turbo Pascal тип Integer был 16-разрядным а типа Cardinal там не было).

Знаковые числа устроены несколько сложнее. Старший из N бит, отводящихся на такое число, служит для хранения знака (этот бит называется знаковым). Если этот бит равен нулю, число считается положительным, а оставшиеся N-1 разрядов используются для хранения числа так же, как в случае беззнакового целого (эти разряды мы будем называть беззнаковой частью). В этом случае знаковое число ничем не отличается от беззнакового. Отрицательные значения кодируются несколько сложнее. Когда все разряды (включая знаковый бит) равны единице, это соответствует значению -1. Рассмотрим это на примере однобайтного знакового числа. Числу -1 в данном случае соответствует комбинация 1 1111111 (знаковый бит мы будем отделять от остальных пробелом), т. е. беззнаковая часть числа содержит максимально возможное значение -127. Числу -2 соответствует комбинация 1 1111110, т. е. в беззнаковой части содержится 126. В общем случае отрицательное число, хранящееся в N разрядах равно X-2N-1, где X — положительное число, хранящееся в беззнаковой части. Таким образом, N разрядов позволяют представить знаковое целое в диапазоне -2N-1..2N-1-1, причем значению -2N-1 соответствует ситуация, когда все биты, кроме знакового равны нулю.

Такая на первый взгляд не очень удобная система позволяет унифицировать операции для знаковых и беззнаковых чисел. Для примера рассмотрим число 11111110. Если его рассматривать как беззнаковое, оно равно 254, если как знаковое, то -2. Вычитая из него, например, 3, мы должны получить 251 и -5 соответственно. Как нетрудно убедиться, в беззнаковой форме 251 — это 11111011. И число -5 в знаковой форме — это тоже 11111011, т. е. результирующее состояние разрядов зависит только от начального состояния этих разрядов и вычитаемого числа и не зависит от того, знаковое или беззнаковое число представляют эти разряды. И это утверждение справедливо не только для выбранных чисел, но и вообще для любых чисел, если ни они, ни результат операции не выходят за пределы допустимого диапазона. То же самое верно для операции сложения. Поэтому в системе команд процессора нет отдельно команд знакового и беззнакового сложения и вычитания — форматы чисел таковы, что можно обойтись одной парой команд (для умножения и деления это неверно, поэтому существуют отдельно команды знакового и беззнакового умножения и деления).

Ранее мы специально оговорили, что такое удобное правило действует только до тех пор, пока аргументы и результат остаются в рамках допустимого диапазона. Рассмотрим, что произойдет, если мы выйдем за его пределы. Пусть в беззнаковой записи нам нужно из 130 вычесть 10. 130 — это 10000010, после вычитания получим 01111000 (120). Но если попытаться интерпретировать эти двоичные значения как знаковые числа, получится, что из -126 мы вычитаем 10 и получаем 120. Такими парадоксальными результатами приходится расплачиваться за унификацию операций со знаковыми и беззнаковыми числами.

Рассмотрим другой пример: из пяти (в двоичном представлении 00000101) вычесть десять (00001010). Здесь уместно вспомнить вычитание в столбик, которое изучается в школе: если в разряде уменьшаемого стоит цифра, большая, чем в соответствующем разряде вычитаемого, то из старшего разряда уменьшаемого приходится занимать единицу. То же самое и здесь: чтобы вычесть большее число из меньшего, как бы занимается единица из несуществующего девятого разряда. Это можно представить так: из числа (1)00000101 вычитается (0)00001010 и получается (0)11111011 (несуществующий девятый разряд показан в скобках: после получения результата мы про него снова забываем). Если интерпретировать полученный результат как знаковое целое, то он равен -5, т. е. именно тому, что и должно быть. Но с точки зрения беззнаковой арифметики получается, что 5-10=251.

Приведенные примеры демонстрировали ситуации, когда результат укладывался в один из диапазонов (знаковый или беззнаковый), но не укладывался в другой. Рассмотрим, что будет, если результат не попадает ни в тот, ни в другой диапазон. Пусть нам нужно сложить 10000000 и 10000000. При таком сложении снова появляется несуществующий девятый разряд, но на этот раз из него единица не занимается, а в него переносится лишняя. Получается (1)00000000. Несуществующий разряд потом игнорируется. С точки зрения знаковой интерпретации получается, что 128 + 128 = 0. С точки зрения беззнаковой — что -128 + (-128) = 0, т. е. оба результата, как и можно было ожидать с самого начала, оказываются некорректными.

Знаковые целые представлены в Delphi типами ShortInt (N=8, диапазон -128..127), SmallInt (N=16, диапазон -32 768..32 767), LongInt (N=32, диапазон -2 147 483 648..2 147 483 647) и Int64 (N=64, диапазон -9 223 372 036 854 775 808..9 223 372 036 854 775 807).

Примечание

32-разрядные процессоры не могут выполнять операции непосредственно с 64-разрядными числами, поэтому компилятор генерирует код, который обрабатывает это число по частям. Сначала операция сложения или вычитания выполняется над младшими 32-мя разрядами а потом — над старшими 32-мя, причем, если в первой операции занималась единица из несуществующего (в рамках данной операции) 33-го разряда или единица переносилась в него, при второй операции эта единица учитывается.

Далее приведены несколько примеров, иллюстрирующих сказанное.

Данный текст является ознакомительным фрагментом.



Поделитесь на страничке

Похожие главы из других книг:

3.2.1.9. Только GLIBC: чтение целых строк: getline() и getdelim()

Из книги автора

3.2.1.9. Только GLIBC: чтение целых строк: getline() и getdelim() Теперь, когда вы увидели, как читать строки произвольной длины, вы можете сделать вздох облегчения, что вам не нужно самим писать такую функцию. GLIBC предоставляет вам для этого две функции:#define _GNU_SOURCE 1 /* GLIBC */#include <stdio.h>#include


Аппаратное переключение контекста

Из книги автора

Аппаратное переключение контекста Так как только что описанным процедурам обработки исключений может потребоваться доступ к привилегированным командам PowerPC, механизм прерываний должен иметь возможность переключать состояние процессора при передаче управления


Аппаратное обеспечение

Из книги автора

Аппаратное обеспечение Популярность услуг IP-телефонии растет с каждым днем – появляются новые операторы, услуги и программы для общения через Интернет. Производители аппаратных средств не отстают – спрос рождает предложение. На рынке высоких технологий сегодня


Аппаратное обеспечение

Из книги автора

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


3. Представление чисел в ЭВМ

Из книги автора

3. Представление чисел в ЭВМ 32-разрядные процессоры могут работать с оперативной памятью емкостью до 232-1, а адреса могут записываться в диапазоне 00000000 – FFFFFFFF. Однако в реальном режиме процессор работает с памятью до 220-1, а адреса попадают в диапазон 00000 – FFFFF. Байты памяти


3.1. Неочевидные особенности целых чисел

Из книги автора

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


5.1. Представление чисел в языке Ruby

Из книги автора

5.1. Представление чисел в языке Ruby Если вы знакомы с любым другим языком программирования, то представление чисел в Ruby не вызовет у вас никакого удивления. Объект класса Fixnum может представлять число со знаком или без знака:237  # Число без знака (положительное).+237 # То же, что


11.20. Представление больших чисел фиксированного размера

Из книги автора

11.20. Представление больших чисел фиксированного размера ПроблемаТребуется выполнить операции с числами, размер которых превышает размер типа long int.РешениеШаблон BigInt в примере 11.38 использует bitset из заголовочного файла <bitset> для того, чтобы можно было представить целые


9.6. $RANDOM: генерация псевдослучайных целых чисел

Из книги автора

9.6. $RANDOM: генерация псевдослучайных целых чисел $RANDOM -- внутренняя функция Bash (не константа), которая возвращает псевдослучайные целые числа в диапазоне 0 - 32767. Функция $RANDOM не должна использоваться для генераци ключей


Пример 22-6. Сравнение двух больших целых чисел

Из книги автора

Пример 22-6. Сравнение двух больших целых чисел #!/bin/bash# max2.sh: Наибольшее из двух БОЛЬШИХ целых чисел.# Это модификация предыдущего примера "max.sh",# которая позволяет выполнять сравнение больших целых чисел.EQUAL=0 # Если числа равны.MAXRETVAL=255 # Максимально возможное


18.3.20. Добавление и проверка целых значений

Из книги автора

18.3.20. Добавление и проверка целых значений В следующем примере рассматривается проверка чисел. Сценарий содержит набор значений счетчика, который легко изменяется при вводе пользователем нового числа. Затем сценарий добавляет это новое значение к постоянному значению,


2.3. Представление чисел в компьютере

Из книги автора

2.3. Представление чисел в компьютере Числовые данные обрабатываются в компьютере в двоичной системе счисления. Числа хранятся в памяти компьютера в двоичном коде, т. е. в виде последовательности нулей и единиц, и могут быть представлены в формате с фиксированной или


Аппаратное и программное обеспечение УЦ и РЦ

Из книги автора

Аппаратное и программное обеспечение УЦ и РЦ При проектировании PKI прежде всего необходимо выбрать программное и аппаратное обеспечение УЦ и РЦ. Выбор в большей степени зависит от поставщиков программных и аппаратных средств, а также от намерения организации создать


2. Представление чисел в ЭВМ. Формализованное понятие алгоритма

Из книги автора

2. Представление чисел в ЭВМ. Формализованное понятие алгоритма 32-разрядные процессоры могут работать с оперативной памятью емкостью до 232-1, а адреса могут записываться в диапазоне 00000000 – FFFFFFFF. Однако в реальном режиме процессор работает с памятью до 220-1, а адреса