1. Представление чисел в ЭВМ: прямой, обратный и дополнительный коды, формат с фиксированной точкой
Представление чисел в ЭВМ: прямой, обратный и дополнительный коды, формат с фиксированной точкой
Для человека число — это абстрактное понятие. Для компьютера — это набор электрических сигналов, интерпретируемых как нули и единицы. Главный вызов инженерной мысли заключался не в том, как сохранить число, а в том, как эффективно выполнять арифметические операции, особенно с отрицательными и дробными числами.
Мы разберем эволюцию представления целых чисел (от прямого кода к дополнительному) и принцип работы чисел с фиксированной точкой, который широко применяется в цифровой обработке сигналов и встроенных системах.
Бит, байт и проблема знака
В основе хранения данных лежит бит — ячейка, принимающая значение 0 или 1. Группы битов образуют байты (8 бит) и машинные слова (16, 32, 64 бита).
Положительные целые числа хранятся как обычный перевод из десятичной системы в двоичную. Например, число 5 в одном байте:
Где индекс указывает на двоичную систему счисления.
Для записи отрицательных чисел инженеры выделили самый старший (левый) бит под знак числа:
* 0 в старшем бите — число положительное. * 1 в старшем бите — число отрицательное.
Этот принцип используется во всех методах кодирования целых чисел.
Прямой код (Sign-Magnitude)
Это наиболее интуитивный способ. Мы берем двоичную запись модуля числа и устанавливаем знаковый бит.
Рассмотрим 8-битные числа:
* в прямом коде: 00000101 * в прямом коде: 10000101
Формально представление описывается так:
Где — представление числа в прямом коде, а — абсолютное значение (модуль) числа .
Недостатки прямого кода
Несмотря на простоту, прямой код имеет два критических недостатка:
Обратный код (Ones' Complement)
Обратный код был попыткой упростить арифметику. Правило формирования:
* Положительные числа: совпадают с прямым кодом. * Отрицательные числа: получаются путем инверсии всех битов положительного числа (0 меняется на 1, 1 на 0).
Пример для числа :
0000010111111010Результат 11111010 — это в обратном коде.
Проблемы обратного кода
Хотя вычитание стало проще (его можно свести к сложению), проблема двух нулей осталась:
* : 00000000
* : 11111111 (инверсия всех нулей)
Из-за этого недостатка обратный код в современных универсальных процессорах практически не используется.
Дополнительный код (Two's Complement)
Это стандарт де-факто в современной вычислительной технике. Дополнительный код решает проблему двух нулей и позволяет выполнять вычитание через сложение без дополнительных корректировок.
Алгоритм получения
Для положительных чисел код совпадает с прямым. Для отрицательных:
Пример для числа :
000001011111101011111010 + 1 = 11111011Результат: 11111011 — это в дополнительном коде.
Математически это выражается формулой для -битного числа:
Где — представление отрицательного числа в дополнительном коде, — разрядность (количество бит), — модуль числа.
Преимущества дополнительного кода
00000000. Инверсия нулей (11111111) плюс единица дает 1 00000000, где единичка переполнения отбрасывается, оставляя чистые нули.Результат 11111101 — это действительно в дополнительном коде (инверсия даст 00000010, плюс 1 = 00000011, то есть 3).
Числа с фиксированной точкой (Fixed Point)
До сих пор мы говорили о целых числах. Но как представить дробь, например, или ? Существует два подхода: плавающая точка (Floating Point, стандарт IEEE 754) и фиксированная точка.
Фиксированная точка — это способ представления дробных чисел, при котором позиция разделителя целой и дробной части жестко зафиксирована.
По сути, компьютер хранит обычное целое число, но программист «договаривается» с машиной, что реальное значение умножено на некий масштабный коэффициент.
Формат Q (Q-notation)
Часто используется запись вида Qn.m, где: * — количество бит для целой части (иногда включая знак). * — количество бит для дробной части.
Рассмотрим 8-битное число в формате Q4.4 (4 бита целых, 4 бита дробных).
Пусть в памяти записано число: 00101100.
Мы мысленно ставим точку посередине: 0010.1100.
Расчет значения
Значение числа рассчитывается как сумма степеней двойки, где дробные разряды имеют отрицательные степени:
Где — итоговое значение, — количество дробных бит, — количество целых бит, — значение бита (0 или 1) в позиции , — вес разряда.
Разберем пример 0010.1100:
* Целая часть 0010:
* Дробная часть 1100:
Посчитаем дробную часть:
Итоговое число: .
Альтернативный взгляд: Масштабирование
Можно смотреть на это проще: мы храним целое число , а реальное значение получаем делением на (где — количество дробных бит).
В нашем примере 00101100 как простое целое равно .
Поскольку у нас 4 дробных бита, делим на :
Где — реальное число, — целочисленное представление в памяти, — масштабный коэффициент.
Плюсы и минусы фиксированной точки
Преимущества: * Скорость: Операции сложения и вычитания выполняются так же быстро, как с обычными целыми числами. Не нужен сопроцессор плавающей точки (FPU). * Точность: Абсолютная погрешность постоянна по всему диапазону чисел.
Недостатки: * Ограниченный диапазон: Мы не можем записывать очень большие и очень маленькие числа одновременно (в отличие от плавающей точки). * Сложность умножения: При перемножении двух чисел формата Q4.4 результат будет иметь формат Q8.8, и его нужно приводить обратно к Q4.4, теряя точность.
Фиксированная точка — основной инструмент в микроконтроллерах, финансовом ПО (где важна точность до копейки и недопустимы ошибки округления плавающей точки) и графике реального времени.