bitlvl
RU

Конвертер дополнительного кода

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

Разрядность
Знаковый бит

Результаты и сообщения этого инструмента выводятся на английском языке.

Как работает дополнительный код

У компьютеров нет знака минус — только биты. Дополнительный код — это соглашение, которое почти каждый CPU использует для хранения отрицательных целых: старший бит (знаковый) считается как отрицательное 2ⁿ⁻¹, а не положительное. В 8 битах старший бит стоит −128, поэтому 1111 1111 = −128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = −1, а 1000 0000 — это −128.

Те же биты, прочитанные как беззнаковые, равны 255 и 128. Является ли значение «на самом деле» отрицательным, решает тип в вашем коде (int8_t против uint8_t), а не биты. Поэтому этот инструмент всегда показывает оба прочтения.

Как получить отрицательное число вручную

  1. Запишите положительное значение в двоичном виде при полной разрядности (42 = 0010 1010).
  2. Инвертируйте каждый бит (1101 0101).
  3. Прибавьте 1 (1101 0110). Это −42, то есть 0xD6 или 214 без знака.

Приём работает в обе стороны: применив его к −42, вы снова получите 42. Инструмент выше выводит эти шаги для любого введённого значения.

Почему он устроен именно так

С дополнительным кодом аппаратуре не нужен отдельный вычитатель. Сложение с отрицательным числом — это обычное двоичное сложение, в котором перенос из старшего бита отбрасывается: 42 + (−42) = 0010 1010 + 1101 0110 = 1 0000 0000, отбрасываем девятый бит, получаем 0. Кроме того, существует только один ноль, в отличие от прямого и обратного кода.

Диапазоны

РазрядностьЗнаковый диапазонБеззнаковый диапазонТипичный тип
8−128 … 1270 … 255int8_t, byte
16−32 768 … 32 7670 … 65 535int16_t, short
32−2 147 483 648 … 2 147 483 6470 … 4 294 967 295int32_t, int
64−9,22 × 10¹⁸ … 9,22 × 10¹⁸0 … 1,84 × 10¹⁹int64_t, long

Отрицательный диапазон на единицу больше положительного, потому что ноль занимает один из «положительных» шаблонов. Поэтому -INT_MIN переполняется: 128 не помещается в знаковый байт.

Вопросы

Что такое −1 в дополнительном коде?

Все единицы: 0xFF в 8 битах, 0xFFFF в 16, 0xFFFFFFFF в 32. Инвертирование 0000 0001 даёт 1111 1110, прибавление 1 даёт 1111 1111.

Как понять, что двоичное число отрицательное?

Посмотрите на самый левый бит при объявленной разрядности. Если он равен 1 и значение знаковое, число отрицательное. 1000 0000 — это −128 как int8, но 128 как uint8; сами по себе биты ничего не решают.

Почему 127 + 1 даёт −128?

Знаковое переполнение. 0111 1111 + 1 = 1000 0000, что устанавливает знаковый бит. В C это неопределённое поведение; в большинстве других языков значение заворачивается к −128.

Что такое расширение знака?

Расширение знакового значения копированием знакового бита в новые старшие биты, так что −1 (0xFF) становится 0xFFFF, а не 0x00FF. Приведение int8 к int16 делает это автоматически; приведение беззнакового значения вместо этого дополняет нулями. Введите отрицательное число и переключайте разрядность выше, чтобы это увидеть.

Знаковый бит — это просто флаг?

Нет. В дополнительном коде знаковый бит имеет значение (−2ⁿ⁻¹) и участвует в арифметике. Этим он отличается от прямого кода, где старший бит лишь отмечает знак, и от чисел с плавающей точкой, где знак — отдельный флаг.