Арифметика

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

1994 год. Intel выпустил Pentium с багом в операции деления. Убыток - 475 миллионов долларов. Причина: ошибка в таблице частичных остатков, то есть в многоразрядном сложении. Каждый раз когда CPU складывает числа - он делает именно то, чему учат в школе столбиком. Только за наносекунды.

  • **Квантизация нейросетей**: INT8/INT4 - замена float32 на целочисленные fixed-point сложения. Apple Neural Engine в M1 делает это для каждого слоя трансформера
  • **Алгоритм Карацубы**: умножение больших чисел через рекурсивные сложения - основа Python BigInteger, Java BigDecimal. Быстрее наивного умножения для чисел длиннее ~70 цифр
  • **Carry lookahead adder**: аппаратное ускорение столбика - параллельный предрасчёт переносов в TPU, Apple Neural Engine, FPGA для ML-инференса

Столбик и перенос разряда

1994 год. Intel выпускает Pentium. Убыток - 475 миллионов долларов из-за ошибки в операции деления. Причина: сбой в таблице частичных остатков, то есть в многоразрядном сложении. Каждый раз когда CPU складывает числа - он делает именно то, чему учат в школе столбиком. Только за наносекунды.

Столбик - это не школьный ритуал. Это алгоритм с переносом разряда, который живёт в каждом ALU (Arithmetic Logic Unit) на планете. Когда Apple Neural Engine складывает тысячи INT8-чисел при квантизации нейросети - он делает именно это, только параллельно в миллионах ячеек.

**Carry lookahead adder** в процессорах предвычисляет все переносы параллельно, не ожидая каждый предыдущий. Именно поэтому сложение 64-битных чисел занимает ~1 такт, а не 64. Алгоритм столбика из школьного учебника - прямой предок этой логики.

Квантизация нейросетей (INT8/INT4) заменяет float32 операции на целочисленные сложения fixed-point чисел. GPT-4 в inference-режиме делает миллиарды таких сложений. Точность квантизации определяется именно правильностью переноса разряда - тем же самым carry.

При сложении 487 + 356 столбиком, какой перенос возникает в разряде десятков?

Вычитание через дополнение

Вычитание - не самостоятельная операция. Это сложение с дополнением. Схема работает одинаково в десятичной и в двоичной - именно поэтому процессор не имеет отдельной схемы вычитания. Вычитатель - это сумматор плюс инвертор.

Two's complement - не только экономия транзисторов. Это математическая элегантность: число кольца Z_n, где -k эквивалентно 2^n - k. Сложение работает автоматически, перенос при переполнении отбрасывается. Алгоритм Карацубы умножает большие числа через рекурсивные сложения - Python BigInteger и Java BigDecimal внутри используют именно его.

**Вычитание столбиком** - это то же дополнение, только в десятичной: при нехватке цифры берётся "в долг" из старшего разряда. Долг = 10 (единица старшего разряда). Дальше - простое сложение с дополненным числом.

Почему процессор не имеет отдельной схемы вычитания?

Устный счёт: разбиение, округление, компенсация

Устный счёт - не про скорость. Про выбор правильного разложения. Это та же идея что в алгоритме Карацубы: большую задачу разбить на маленькие, которые решаются дешевле. Карацуба умножает 1000-значные числа через три сложения вместо четырёх - рекурсивно, до базового случая.

Все четыре приёма используют одно свойство: ассоциативность и коммутативность сложения. Вычитание этими свойствами не обладает - поэтому в приёме с дополнением важен порядок. 521 - 198 = 521 - 200 + 2, но не 521 + 200 - 2.

**Золотое правило:** превращай неудобные числа в круглые и компенсируй разницу. 99 + 47 = 100 + 47 - 1 = 146. Это не хитрость - это дистрибутивность в действии.

Вычитание - это просто сложение наоборот, со всеми теми же свойствами

Вычитание теряет коммутативность и ассоциативность

7 - 3 = 4, но 3 - 7 = -4. (10 - 5) - 2 = 3, но 10 - (5 - 2) = 7. CPU это учитывает при компиляции арифметических выражений.

Как быстрее посчитать 998 + 347 в уме?

Ключевые идеи

  • Столбик = поразрядное сложение с переносом (carry); перенос - атомарная операция ALU
  • Вычитание реализуется через дополнение: a - b = a + (-b); two's complement в CPU - та же логика
  • Сложение коммутативно и ассоциативно; вычитание - нет; это определяет какие приёмы допустимы
  • Приёмы устного счёта - дополнение до круглого, разбиение, компенсация - все строятся на ассоциативности

Связанные темы

Сложение и вычитание - основа для более сложных операций:

  • Умножение и деление — Умножение - повторное сложение; алгоритм Карацубы через рекурсивные сложения
  • Целые числа и модуль — Знаки и абсолютное значение - основа для операций над Z
  • Порядок операций — Когда применять +/- в составных выражениях
  • Двоичная система — Столбик в базе 2 - язык процессора
  • Компьютерная арифметика — Переполнение, carry lookahead, целочисленные операции в железе

Вопросы для размышления

  • Pentium FDIV-баг был в делении, но его fix потребовал переработки всей арифметической pipeline. Почему ошибка в одной операции затрагивает сложение?
  • Почему вычитание не коммутативно, а сложение - да? Что изменилось бы в алгебре если бы было наоборот?
  • Алгоритм Карацубы умножает через рекурсивные сложения. Почему это быстрее прямого умножения?

Связанные уроки

  • ar-02-integers — Целые числа и знаки - фундамент операций
  • ar-04-multiplication — Умножение - повторное сложение; столбик масштабируется
  • ar-05-order — Порядок операций определяет когда применять +/-
  • ar-26-binary — Двоичное сложение - тот же алгоритм столбика в базе 2
  • ar-28-modular — Модулярное сложение - перенос разряда по кольцу Z_n
  • ar-45-computer-arithmetic — Carry lookahead adder - аппаратный столбик в ALU
  • calc-01-sequences
Сложение и вычитание

0

1

Войти