Комбинационные схемы: полусумматор

Урок строит из вентилей первую полезную схему — сумматор, складывающий двоичные числа.

Полусумматор — комбинационная схема, складывающая два одноразрядных двоичных числа и выдающая сумму и перенос.

Как процессор складывает числа? С помощью сумматоров — схем из вентилей. Полусумматор — первый шаг к арифметико-логическому устройству.

Полусумматор

Складывая два бита $a$ и $b$, получаем два выхода: сумму $S$ (младший бит) и перенос $C$ (старший бит). По таблице истинности видно, что

$$ S = a \oplus b \;(\text{XOR}), \qquad C = a \cdot b \;(\text{AND}). $$

Например, $1 + 1 = 10_2$: сумма $S = 0$, перенос $C = 1$.

Полный сумматор

Полусумматор не учитывает перенос из младшего разряда. Полный сумматор имеет три входа ($a$, $b$, входной перенос $C_{in}$) и складывает их, выдавая сумму и выходной перенос. Соединяя полные сумматоры в цепочку, складывают многоразрядные числа — так устроены процессоры.

Сумматор в Python

def half_adder(a, b):
    s = a ^ b      # сумма (XOR)
    c = a & b      # перенос (AND)
    return s, c

def full_adder(a, b, cin):
    s1, c1 = half_adder(a, b)
    s, c2 = half_adder(s1, cin)
    return s, c1 | c2

print("Полусумматор:")
for a in (0,1):
    for b in (0,1):
        s, c = half_adder(a, b)
        print(f"  {a}+{b} -> сумма={s}, перенос={c}")

# Сложение 3-битных чисел 011 (3) и 101 (5)
A, B = [1,1,0], [1,0,1]   # младший бит первым
res, carry = [], 0
for i in range(3):
    s, carry = full_adder(A[i], B[i], carry)
    res.append(s)
res.append(carry)
print("3 + 5 =", int(''.join(str(b) for b in reversed(res)), 2))

Вывод:

Полусумматор:
  0+0 -> сумма=0, перенос=0
  0+1 -> сумма=1, перенос=0
  1+0 -> сумма=1, перенос=0
  1+1 -> сумма=0, перенос=1
3 + 5 = 8

Как работает под капотом

Сумматор — наглядный пример того, как из простой логики рождается арифметика. XOR даёт «сумму без переноса» (ведь $1+1$ в одном разряде даёт 0 с переносом), а AND ловит момент переноса. Полный сумматор склеивает два полусумматора и объединяет переносы через OR. Соединяя $n$ полных сумматоров в «гирлянду» (ripple-carry), процессор складывает $n$-битные числа: перенос «бежит» от младшего разряда к старшему, как при сложении столбиком. Именно поэтому в коде мы перебираем биты от младшего к старшему, передавая carry дальше. Реальные процессоры используют ускоренные схемы переноса, но идея та же — вся арифметика сводится к комбинациям XOR, AND и OR.

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

  • Используют полусумматор для многоразрядного сложения, забывая про входной перенос.
  • Путают порядок бит: в коде удобно хранить младший бит первым.
  • Берут OR вместо XOR для суммы — тогда $1+1$ даст неверный результат.

Итог

  • Полусумматор: $S = a \oplus b$, $C = a \cdot b$.
  • Полный сумматор учитывает входной перенос.
  • Цепочка сумматоров складывает многоразрядные числа.
  • Так процессоры выполняют арифметику.
Проверьте себя
1. Какими вентилями реализуется полусумматор?
AAND для суммы, XOR для переноса
BXOR для суммы, AND для переноса
COR для суммы, NOT для переноса
DТолько NAND
2. Чем полный сумматор отличается от полусумматора?
AИмеет вход переноса из младшего разряда
BСкладывает три бита одновременно без переноса
CРаботает только с нулями
DНе выдаёт перенос