Сложение и вычитание в столбик

Учимся складывать и вычитать прямо в двоичной системе — так же, как в столбик в начальной школе, только цифр всего две.

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

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

Зачем это нужно

Во-первых, это экзаменационная тема: задания на арифметику в недесятичных системах есть и в ОГЭ, и в первой части ЕГЭ. Во-вторых, без сложения в столбик не понять следующий урок про дополнительный код — там вычитание заменяется сложением. В-третьих, это снимает «магию»: когда видишь, что 0b101 + 0b011 даёт 0b1000, начинаешь доверять процессору, а не заучивать результаты.

Таблица сложения двоичных цифр

Вся арифметика держится на четырёх правилах для одного разряда. Запомнить их легко:

Слагаемое AСлагаемое BПеренос на входБит результатаПеренос на выход
00000
01010
11001
11111

Ключевой случай — последняя строка: 1 + 1 + 1 = 11 в двоичной, то есть в текущем разряде остаётся 1, а единица уходит в перенос. По-научному это записывают через сумму по модулю 2 и перенос:

$$ s_i = a_i \oplus b_i \oplus c_i, \qquad c_{i+1} = (a_i \land b_i) \lor (c_i \land (a_i \oplus b_i)) $$

Здесь $\oplus$ — это «исключающее ИЛИ» (XOR), $\land$ — И, $\lor$ — ИЛИ. Бит результата $s_i$ равен 1, когда среди трёх входов (два бита и входной перенос) нечётное число единиц. Именно так устроен полный сумматор внутри процессора.

Складываем в столбик: пример

Сложим $1011_2$ (это 11) и $0110_2$ (это 6). Ожидаем 17, то есть $10001_2$. Идём справа налево, столбец за столбцом; строку переносов пишем сверху:

32168421
Перенос111
A1011
B0110
Сумма10001

Разбор по разрядам справа налево: разряд 1 — это 1+0=1; разряд 2 — 1+1=10, пишем 0, переносим 1; разряд 4 — 0+1+1(перенос)=10, пишем 0, переносим 1; разряд 8 — 1+0+1(перенос)=10, пишем 0, переносим 1; разряд 16 — 0+0+1(перенос)=1. Получили $10001_2 = 17$. Сходится.

Вычитание: занимаем из старшего разряда

Вычитание в столбик работает с заёмом (borrow): если из 0 нужно вычесть 1, берём 1 из соседнего старшего разряда, и в текущем получается 10 − 1 = 1 (то есть 2 минус 1). Вычтем $1011_2$ (11) минус $0110_2$ (6), ждём 5, то есть $101_2$:

8421
Заём−1
Уменьшаемое1011
Вычитаемое0110
Разность0101

Разряд 1: 1−0=1. Разряд 2: 1−1=0. Разряд 4: 0−1 — не хватает, занимаем из разряда 8; получается 10−1=1 в этом разряде, а разряд 8 уменьшается на 1. Разряд 8: было 1, стало 1−1=0 (вычитаемое там 0, но мы отдали 1 в заём). Итог $0101_2 = 5$.

Сложение в восьмеричной и шестнадцатеричной системах

Тот же принцип, но «потолок» разряда теперь 8 или 16. В восьмеричной перенос возникает, когда сумма в столбце достигает 8. Сложим $57_8 + 26_8$. Младший разряд: 7+6=13 в десятичной, а это $13 = 1 \cdot 8 + 5$, значит пишем 5, переносим 1. Старший разряд: 5+2+1=8, а $8 = 1 \cdot 8 + 0$, пишем 0, переносим 1. Итог: $105_8$. Проверка: $57_8 = 47$, $26_8 = 22$, сумма 69; а $105_8 = 64 + 5 = 69$. Совпало.

В шестнадцатеричной перенос на 16, а цифры идут до F (15). Сложим $1A_{16} + 0F_{16}$. Младший разряд: $A + F = 10 + 15 = 25 = 1 \cdot 16 + 9$, пишем 9, переносим 1. Старший: $1 + 0 + 1 = 2$. Итог $29_{16}$. Проверка: $1A_{16} = 26$, $0F_{16} = 15$, сумма 41; а $29_{16} = 2 \cdot 16 + 9 = 41$. Верно.

Как это работает

Процессор не знает «десятичной системы» вообще. У него есть электронная схема — полный сумматор, реализующий формулу выше: на вход три бита (два слагаемых и перенос), на выход бит суммы и бит переноса. Цепочка таких сумматоров, соединённых через перенос, складывает целые слова (8, 16, 32, 64 бита) за один такт. Вычитание процессор обычно не делает отдельной схемой — он сводит его к сложению с дополнительным кодом, об этом следующий урок. Восьмеричная и шестнадцатеричная системы для процессора — просто удобная запись тех же битов группами по 3 и по 4: $1A_{16} = 0001\,1010_2$, и арифметика под капотом всё равно двоичная.

Проверять себя удобно на Python: функция bin() печатает двоичную запись с префиксом 0b, а int("1011", 2) читает строку как число в указанной системе.

a = 0b1011  # 11
b = 0b0110  # 6
s = a + b
print("A =", a, "=", bin(a))
print("B =", b, "=", bin(b))
print("A + B =", s, "=", bin(s))
print("A - B =", a - b, "=", bin(a - b))
# проверка восьмеричной и шестнадцатеричной
print("57(8) + 26(8) =", oct(int("57", 8) + int("26", 8)))
print("1A(16) + 0F(16) =", hex(int("1A", 16) + int("0F", 16)))

Вывод:

A = 11 = 0b1011
B = 6 = 0b110
A + B = 17 = 0b10001
A - B = 5 = 0b101
57(8) + 26(8) = 0o105
1A(16) + 0F(16) = 0x29

Префиксы 0b, 0o, 0x — это служебные пометки Python для двоичной, восьмеричной и шестнадцатеричной записи; на экзамене их не пишут, но в коде они подсказывают систему счисления.

Частые ошибки

  • Забывают перенос. В случае 1+1 пишут 1 вместо 0 и теряют единицу переноса. Всегда держите строку переносов сверху.
  • Путают «потолок» системы. В восьмеричной перенос на 8, а не на 10; легко машинально сложить «как в десятичной». Проверяйте через десятичную систему.
  • В вычитании забывают уменьшить старший разряд после заёма. Заняли 1 — значит соседний слева разряд стал на 1 меньше.
  • Считают, что A − B всегда положительно. Если уменьшаемое меньше вычитаемого, результат отрицателен — и его уже нельзя записать обычными битами без знака. Как это решается — в следующем уроке.

Итоги

  • Двоичное сложение идёт справа налево с переносом, когда сумма разряда достигает 2.
  • Вычитание использует заём: 10 − 1 = 1 в текущем разряде, старший разряд уменьшается.
  • В восьмеричной перенос наступает на 8, в шестнадцатеричной — на 16; цифры идут до 7 и до F.
  • Любую ручную выкладку легко проверить через десятичную систему и функциями bin() / int(s, base) в Python.
Проверьте себя
1. Сложите двоичные числа 1101 и 0011 в столбик. Какой получится результат?
A1110
B10000
C1111
D10010
2. Чему равна сумма 7(8) + 5(8) в восьмеричной системе?
A12
B14
C10
DC