Print
Category: Теоретическая информатика
Hits: 30861

В этом материале мы заглянем в машинную память и узнаем, как в ней хранятся числа. Это весьма непростой вопрос, начнем с того, что чисел любых хоть целых, хоть вещественных бесконечное количество, а это значит, что «все числа» мы не сможем поместить в конечную машинную память, какой бы большой она не была. Нужны способы, чтобы закодировать как можно больше чисел, да еще с как можно большей точностью. Для этого применяются два главных принципа:

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

Хранение целых чисел

для хранения целых чисел зарезервировано несколько типов, вот, например, типы, используемые для хранения целых чисел в классическом языке Pascal

Название типа: Длина (в байтах): Диапазон значений:
Byte 1 0..255
ShortInt 1 -128..+127
Word 2 0..65535
Integer 2 -32768..+32767
LongInt 4 -2 147 483 648..+2 147 483 647

Как видно из таблицы разные типы занимают в машинной памяти, разное количество байт. Это и понятно, язык зародился в то время, когда машинная память была очень дорога, размеры ее невелики, и программист всеми силами ее экономил. Так, если в задаче переменная не превысит значение 255 (например, номер месяца в году), достаточно однобайтовой ячейки, в ней числа могут принять 255 различных значений от восьми нулей (0) до восьми единиц (255). В случае, если в задаче переменная принимает больший диапазон значений, необходим другой тип, например, integer.

Рассмотрим принцип хранения чисел в двухбайтовых чисел «со знаком» - тип integer.

Если число положительное, то все просто – переводим число в двоичную систему и добавляем незначащие нуди, чтобы число занимало строгие 16 разрядов. Например, переведем число целое десятичное 22:

22(10) = 1 0110(2) = 0000 0000 0001 0110

С отрицательным числом все несколько сложнее. Приведем в качестве примера число -22:

1. получаем машинный код модуля исходного числа: 0000 0000 0001 0110
2. инвертируем число (нули заменяем единицами, а единицы нулями): 1111 1111 1110 1001
3. к полученному числу прибавляем единицу: 1111 1111 1110 1010

Полученное машинное число и есть число -22 и носит название «обратный код». Такой, на первый взгляд странный способ хранения отрицательных чисел значительно облегчает вычитание чисел. Для того чтобы выполнить действие A – B, компьютер на самом деле выполняет A + (-B). Покажем это на примере:

Целое число 10 в машинном коде принимает значение: 0000 0000 0000 1010
Целое число -10 преобразованное в машинный код по описанному выше алгоритму примет значение: 1111 1111 1111 0110

Теперь выполнив сложение 22 + (-22) нетрудно убедиться:

Единица, которая образуется при сложении чисел, переходит в семнадцатый разряд. Но так как число шестнадцатиразрядное, эта единица исчезает бесследно. Остается ноль, что, впрочем, и ожидалось.

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

Предположим, нужно перевести машинное число 1111 1111 1101 1101 в десятичный эквивалент:

отнимаем единицу: 1111 1111 1101 1100
инвертируем число: 0000 0000 0010 0011
отбрасываем незначащие нули: 10 0011
переводим двоичное число в десятичное: 25 + 21 + 20 = 32 + 2 + 1 35
наше исходное число -35


Схема хранения целого числа «со знаком» в машинной памяти

Максимальным числом при данном способе хранения чисел станет 0111 1111 1111 1111 = 216 – 1= 32767.

Важное замечание: в других вариациях языка, например, в Pascal ABC тип integer занимает 4 байта, и соответственно, диапазон у такой переменной больше.

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


Таблица переводит целое число в шестнадцатиразрядный машинный код.

Хранение вещественных чисел

Самый простой способ хранения вещественных чисел – выделить в общей ячейке числа несколько разрядов под хранения десятичной части, такой способ хранения называется числами с фиксированной запятой. Он вполне подходит для расчетах в кассовых аппаратах и как оказывается не только в них. Но этот способ совершенно не подходит для точных расчетов. Для них используются числа с плавающей точкой. Их способ хранения описывает специальный стандарт IEEE754, он используется аппаратно (например, в процессорах), а также программно (например, в компиляторах языков программирования). Разберемся в нем.

Одно и то же с точки зрения математики число можно записать разными наборами цифр:

75,77245 =  7577,245*10-2 = 7,577245*101

Не смотря на то, что первый способ нам кажется более привычным, в компьютере используется последняя запись. Любое вещественное число в памяти компьютера представлено двумя числами:

  1. мантисса (в нашем примере 7,577245) мантисса всегда находится в интервале (1, q) где q - основания системы счисления;
  2. порядок (в нашем примере порядок равен 1)

Приведение числа к такому виду называют нормализацией. Так как компьютер работает с двоичными числами, то мантисса, порядок – двоичные числа.

для хранения вещественного числа типа Float (Single) используют ячейку памяти размером в 4 байта, 32 ячейки которой распределены следующим образом:

 

Получение машинной записи вещественного числа лучше всего рассмотреть на примере.

Возьмем десятичное число -23,75
Переведем модуль числа в двоичный вид: 10111,11
Нормализуем полученное двоичное число: 1,011111*24 = 1,011111*2100
Как легко заметить мантисса любого двоичного числа начинается с единицы, поэтому ее принято отбрасывать, не забывая при этом. Добавляем к мантиссе незначащие нули, так чтобы в сумме от нанимали 23 разряда 0111110 00000000 00000000
Так как число отрицательное – старший разряд числа единица (в отличие от целых чисел обратный код для вещественных чисел не используется) 1
Так как знак порядка в вещественном числе не хранится, весь диапазон возможных степеней распределяется следующим образом: первые 128 чисел отводятся под отрицательные значения, а следующие 128  чисел под положительные. Иными словами к полученному значению порядка нужно прибавить 127 (011111112). Порядок нашего числа примет значение: 10000011
Итоговое машинное число примет вид (разделение байтов сделано для удобства восприятия): 11000001 10111110 00000000 00000000

Очень любопытный сервис, расположенный по адресу: http://www.binaryconvert.com/ позволит увидеть код чисел различных типов. Сервис на английском языке, но это не должно вас смутить, все очень просто:


Шаг 1. Выбираем нужный тип числа, нажимаем на кнопку «Convert»


Шаг 2. Вводим нужное число (дробная часть отделяется точкой), нажимаем на кнопку «Convert to binary», смотрим результат.

Как легко заметить полученный код числа -23,75 соответствует значению, полученному нами ранее.

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

а как на самом деле

Но это все теория. А как на самом деле хранятся числа в памяти компьютера, причем не какого-то абстрактного, а вашего? Это очень просто узнать.

Достаточно написать и запустить в среде программирования следующую короткую программу:

program debag;
var
    z: integer;
    f: file of integer;        
begin
    assign(f,'1.dat');
    Rewrite(f);
    z:=-10;
    write(f,z);
    close(f);
end.

Эта программа создает типизированный файл, т.е. файл содержащий не текст, а переменные заданного типа, в данном случае – целые числа. После запуска компьютер создаст файл 1.dat, в котором будет всего одно целое число -10. Если открыть этот файл шестнадцатеричным редактором, можно увидеть его содержимое:


Содержимое файла 1.dat

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

Мы видим, что в данном конкретном случае типизированный файл 1.dat с единственным целым числом -10  занимает 4 байта памяти. Переведя каждое двухзначное шестнадцатеричное число в двоичный эквивалент, мы получим двоичный машинный код числа -10 в языка Pascal ABC:

11110110 11111111 11111111 11111111

Как легко проверить, он сильно отличается от числа 11111111 11110110 полученного нами ранее. И дело не только в том, что в теории для числа integer в Pascal ABC Используется четыре байта, а не два. Дело в том, что в Pascal порядок байтов другой!

Может быть все дело в том, что типизированный файл «пишется с конца»? А вот и нет, в этом легко убедиться если записать в файл два числа. Они запишутся в той последовательности, как они идут в программе. И это не изменение последовательности разрядов, это именно изменение порядка байтов составляющих число.

Если мы изменим две строчки в программном коде, мы получим файл, содержащий вещественное число -10.



Программа формирует типизированный файл с вещественным числом -10 «внутри».

Открыв полученный файл в шестнадцатеричном редакторе мы увидим содержимое этого файла:

 

Вещественное число в Pascal ABC занимает 8 байтов:

00000000 00000000 00000000 00000000 00000000 00000000 00100100 11000000

И снова порядок байтов не тот, что должен появиться в теории на основании стандарта IEEE754 или как сформирует восьмибайтовое число уже описанный выше интернет сервис:


Машинный код вещественного числа -10 соответственно стандарта IEEE754

Последовательность байтов в восьмибайтовом в вещественном числе -10, построенном на основании стандарта IEEE754 иное, нежели показывает нам шестнадцатеричный редактор.

P.S.

Тема хранения чисел в памяти компьютера в школе затрагивается «вскользь». Задач об этом в Едином экзамене нет, по крайней мере, пока. Означает ли это, что это не нужно обсуждать с учениками? Я считаю нужно обязательно!

Во-первых, это чертовски интересно.

Во-вторых, стремление «дойти до самой сути» важное качество личности, которое и должна воспитывать школа.

И, в-третьих, ставя высокую планку добиваешься высоких результатов.

Во вложении к данному материалу:

  1. Спец. выпуск газеты «Информатика», №1, 2011 г. Тема номера: «Компьютерная арифметика», в том числе очень внятно и подробно рассказывается о хранении чисел в памяти компьютера. Каждый раздел сопровождается вопросами и задачами.
  2. Два практических задания на получение машинного кода в среде электронных таблиц.

 

Attachments:
Download this file (Компьютерная арифметика.pdf)Компьютерная арифметика.pdf[спец. выпуск газеты «Информатика», №1, 2011 г.]2770 kB
Download this file (Машинный код 1 - целые числа.xls)Машинный код 1 - целые числа.xls[Практическое задание]29 kB
Download this file (Машинный код 2 - вещественные числа.xls)Машинный код 2 - вещественные числа.xls[Практическое задание]30 kB