THRESHOLD — TECHNICAL FIELD GUIDE / ТЕХНИЧЕСКИЙ СПРАВОЧНИК
PHASECOMMON GROUND
REGIME—
STATUS—
← ОГЛАВЛЕНИЕ — РИС. 00 — ВСЁ, ЧТО ЗНАЕТ КОМПЬЮТЕР, — ЭТО ДВА УРОВНЯ НАПРЯЖЕНИЯ БУЛЬ, 1854

ПОРОГ
ОБЩАЯ ОСНОВА И БАЗОВАЯ ЛОГИКА: ОТ ОДНОГО ПРОВОДА ДО РАБОТАЮЩЕЙ ПРОГРАММЫ

Тринадцать глав с настоящими таблицами истинности и формулами о том, почему компьютеру нужно всего два уровня напряжения, как И, ИЛИ и НЕ собирают любое решение программы, как цепочка else-if и классический вопрос с собеседований FizzBuzz применяют эту логику на практике, как двоичные числа складываются и вычитаются без единого знака минус, почему один точно поставленный IF побеждает миллион сравнений, и как проследить всю программу, шаг за шагом, от входных данных до последствий. Пролистайте вниз, чтобы начать.

НАЧАТЬ — ГЛАВА 01 →
CH.01 / 13 — ОБЩАЯ ЗЕМЛЯ

Прежде чем появятся 1 и 0, нужен общий для всех уровень 0 В

Любое измерение напряжения — это сравнение, а не абсолютное число. Фраза «на проводе пять вольт» имеет смысл только тогда, когда всё остальное в схеме согласно с тем, что считать нулём, — с общей точкой отсчёта, землёй. Напряжение любого провода, высокое или низкое, — это на самом деле просто «насколько выше земли».

Цифровая логика использует эту общую землю, чтобы провести черту. Всё, что близко к земле, читается как LOW — цифра 0. Всё, что близко к напряжению питания, читается как HIGH — цифра 1. Промежуток между ними намеренно оставлен неопределённым, чтобы небольшая электрическая помеха никогда не превратила уверенный 0 в случайную 1.

КЛАССИЧЕСКИЕ УРОВНИ 5V TTL-ЛОГИКИ
LOW: 0 – 0.8V   UNDEFINED: 0.8 – 2.0V   HIGH: 2.0 – 5.0V
Неопределённый промежуток — это запас помехоустойчивости: буфер, не позволяющий немного зашумлённому проводу быть прочитанным неверно.
НАПРЯЖЕНИЕ НА ПРОВОДЕ1.40V
UNDEFINED
ЗНАЧЕНИЕ БИТА: —
CH.02 / 13 — ОДИН ПРОВОД, ДВА СОСТОЯНИЯ, БЕСКОНЕЧНЫЙ СМЫСЛ

Один провод умеет говорить только «да» или «нет». Проводов достаточно — и можно сказать что угодно.

Один провод в схеме из главы 1 несёт ровно один бит — одно «да» или «нет», HIGH или LOW. Сам по себе он не очень выразителен. Но выстройте в ряд несколько проводов — и каждая возможная комбинация их состояний становится отдельным узором; а всё, что представляет компьютер — числа, буквы, цвета, звук, — это просто имя, данное одному из этих узоров.

Добавьте ещё один провод — и число возможных узоров удваивается, потому что каждый узор, который могли составить прежние провода, теперь встречается дважды: один раз с новым проводом LOW, один раз — HIGH. Именно это удвоение объясняет, почему двоичная система вообще важна не только математикам: это ровно то, что даёт реальное количество проводов.

ЧИСЛО СОСТОЯНИЙ ПРИ n ПРОВОДАХ (БИТАХ)
N = 2ⁿ
8 проводов (байт): 2⁸ = 256 состояний — достаточно для любого символа в этом предложении. 4 провода (тетрада, полубайт): 2⁴ = 16 — ровно одна шестнадцатеричная цифра.
ЧИСЛО ПРОВОДОВ (БИТ), n8
256
ВЕХА: ОДИН БАЙТ — ДОСТАТОЧНО ДЛЯ ЛЮБОГО СИМВОЛА В ЭТОМ ПРЕДЛОЖЕНИИ
CH.03 / 13 — ЛОГИЧЕСКИЕ ЭЛЕМЕНТЫ: ТРИ НЕОБХОДИМЫХ

Любое решение компьютера сводится к трём небольшим схемам

Логический элемент — это схема с одной задачей: посмотреть на входные напряжения и выдать HIGH или LOW по фиксированному правилу. Таких правил, которые стоит знать, немного, и всего трёх из них — И, ИЛИ и НЕ — достаточно, чтобы построить любое другое, включая каждое ветвление, которое когда-либо делает программа.

И выдаёт HIGH, только если оба входа HIGH. ИЛИ выдаёт HIGH, если хотя бы один вход HIGH. НЕ просто переворачивает то, что получает. Выберите элемент ниже, переключите входы — и посмотрите на его решение.

ВЫХОД
0
CH.04 / 13 — КОМБИНИРУЯ ЭЛЕМЕНТЫ: XOR И ЗАКОНЫ ДЕ МОРГАНА

Из комбинирования И, ИЛИ и НЕ рождаются два полезных сокращения

XOR («исключающее ИЛИ») выдаёт HIGH, когда входы не совпадают — ровно один из них HIGH, но не оба. Это не четвёртый фундаментальный элемент: соедините ИЛИ, И и два НЕ — и получите ровно ту же таблицу истинности. XOR заслуживает собственного обозначения лишь потому, что это именно та схема, которая складывает два бита, — см. главу 8.

Законы де Моргана — другое полезное сокращение: отрицание И равносильно ИЛИ от отрицаний, а отрицание ИЛИ равносильно И от отрицаний. Именно поэтому «не (идёт дождь и холодно)» означает ровно то же самое, что «не идёт дождь, или не холодно», — что на русском, что в кремнии.

ЗАКОНЫ ДЕ МОРГАНА
¬(A ∧ B) = ¬A ∨ ¬B     ¬(A ∨ B) = ¬A ∧ ¬B
∧ = И, ∨ = ИЛИ, ¬ = НЕ — те же три элемента из главы 3, записанные символами.
CH.05 / 13 — IF, THEN, ELSE: ЛОГИКА СТАНОВИТСЯ РЕШЕНИЕМ

Слово «если» — это логический элемент в другой одежде

Любой обычный языковой союз соответствует одному из элементов главы 3: «и» / «также» / «оба» — это И; «или» / «либо» — это ИЛИ; «не» — это НЕ. Скажите «если идёт дождь или наступила ночь, включи фары» — и вы уже написали элемент ИЛИ, просто ещё не нарисовали его.

Конструкция if/then/else пропускает выход элемента через развилку: путь THEN — когда условие HIGH, путь ELSE — когда LOW. Электрически ничего нового не происходит: это тот же элемент из главы 3, только теперь он решает, какая из двух инструкций реально выполнится.

AND
ТАКЖЕ, ОБА, И ТО И ДРУГОЕ
OR
ЛИБО, ИЛИ, В ИНОМ СЛУЧАЕ
NOT
НЕ, НЕТ, ПРОТИВОПОЛОЖНОЕ
IF raining OR night: headlights = ONELSE: headlights = OFF
CH.06 / 13 — ЛЕСТНИЦЫ ELSE-IF: ГДЕ АЛГОРИТМЫ ПРИМЕНЯЮТ IF

Настоящий код редко останавливается на одной развилке — их выстраивают в цепочку

Условие if/else из главы 5 выбирает лишь между двумя путями. Большинству реальных решений нужно больше двух вариантов, поэтому код выстраивает условия в лестницу: IF, затем серия ELSE IF, а в конце — ELSE как вариант по умолчанию. Компьютер проверяет каждую ступень сверху вниз и останавливается на первой, которая оказалась HIGH, — все ступени ниже полностью пропускаются, даже если они тоже были бы истинны.

Классический пример — шкала оценок: балл 85 технически также «не меньше 70» и «не меньше 60», но оценку присваивает только первая сработавшая ступень — «не меньше 80». Порядок важен: переставьте ступени лестницы местами — и балл 95 может случайно получить оценку F. Подвиньте ползунок балла ниже и посмотрите, какая ступень сработает.

IF score >= 90: grade = "A"ELSE IF score >= 80: grade = "B"ELSE IF score >= 70: grade = "C"ELSE IF score >= 60: grade = "D"ELSE: grade = "F"
БАЛЛ72
C
CH.07 / 13 — СЧЁТ БЕЗ ДЕСЯТИ ПАЛЬЦЕВ

Десятичная система считает десятками, потому что у нас десять пальцев. Двоичная считает двойками, потому что у провода два состояния.

Десятичный разряд — это степени десяти: цифра «3» в «300» означает 3×10². Двоичный разряд работает так же, только со степенями двойки — каждый бит вдвое «весомее» соседнего справа: бит HIGH добавляет к сумме степень двойки своей позиции, а бит LOW не добавляет ничего.

Это и есть весь алгоритм, которым компьютер превращает ряд проводов в понятное человеку число: сложить степени двойки для всех битов со значением HIGH. Переключайте биты ниже — они уже выставлены на одно известное число — и наблюдайте, как десятичное значение меняется в реальном времени.

ВЕС РАЗРЯДА В ПОЗИЦИИ i
value = 2i
Бит 0 (крайний справа) стоит 1, бит 1 — 2, бит 2 — 4, бит 3 — 8 и так далее — удвоение с каждым шагом влево.
42
ДЕСЯТИЧНОЕ ЗНАЧЕНИЕ
CH.08 / 13 — СЛОЖЕНИЕ В ДВОИЧНОЙ СИСТЕМЕ: СУММАТОР

Сложение — это XOR с памятью о только что случившемся переполнении

Сложение двух отдельных битов требует двух ответов: собственно суммы и того, произошло ли переполнение в следующий разряд, — переноса. Один только XOR вычисляет сумму (HIGH ровно тогда, когда биты не совпадают, — это и есть сложение без переноса), а один только И вычисляет перенос (переполнение даёт только 1+1). Эта пара называется полусумматором.

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

ПОЛУСУММАТОР
Sum = A ⊕ B     Carry = A ∧ B
ЧИСЛО A
ЧИСЛО B
CH.09 / 13 — FIZZBUZZ: НОВЫЙ ОПЕРАТОР ВСТРЕЧАЕТ ЛЕСТНИЦУ

Лестница из главы 6, прогнанная для каждого числа, — знаменитый вопрос на собеседовании

Остаток от деления — оператор % — это то, что остаётся после деления: 10 % 3 равно 1, потому что 3 умещается в 10 три раза, а 1 остаётся. «n делится на 3» — это просто короткая запись «n % 3 равно 0».

FizzBuzz — знаменитая разминка для собеседований по программированию — это просто лестница из главы 6, прогоняемая для каждого числа: вывести «FizzBuzz», если число делится и на 3, и на 5, «Fizz» — если только на 3, «Buzz» — если только на 5, иначе — само число; и эта двойная проверка обязана стоять на верхней ступени лестницы, иначе до неё просто не дойдёт очередь. Подвиньте N и посмотрите, как пересчитывается вся последовательность.

ОСТАТОК ОТ ДЕЛЕНИЯ (MODULO)
a % b = remainder of a ÷ b
FOR n FROM 1 TO N: IF n % 3 == 0 AND n % 5 == 0: PRINT "FizzBuzz" ELSE IF n % 3 == 0: PRINT "Fizz" ELSE IF n % 5 == 0: PRINT "Buzz" ELSE: PRINT n
СЧИТАТЬ ДО N30
CH.10 / 13 — ВЫЧИТАНИЕ БЕЗ ЗНАКА МИНУС

Отдельной схемы вычитания не существует. Она и не была нужна.

Строить отдельную вторую схему только ради вычитания было бы расточительно — сумматор из главы 8 уже есть. Дополнительный код решает эту задачу: инвертируйте каждый бит числа и прибавьте 1 — и результат в любых вычислениях будет вести себя точно как его отрицательное значение. Вычитание B из A превращается в сложение A с (−B) — тот же сумматор, без нового «железа».

Этот приём также даёт отрицательным числам место среди обычных битов: при 4 битах 0111 — это +7, а 1000 — это −8, и всё промежуточное аккуратно встаёт на свои места, а старший бит бесплатно становится флагом знака: 0 — для неотрицательных, 1 — для отрицательных.

ДОПОЛНИТЕЛЬНЫЙ КОД (ОТРИЦАНИЕ n-БИТНОГО ЧИСЛА)
−x = (¬x) + 1
Пример, 4 бита: +3 = 0011 → инверсия = 1100 → +1 = 1101 = −3.
CH.11 / 13 — БИНАРНЫЙ ПОИСК: IF В МАСШТАБЕ

Угадывайте умнее, а не усерднее — один точно поставленный IF побеждает миллион

Наивный поиск по отсортированному списку проверяет каждую запись, пока не найдёт совпадение, — в худшем случае N сравнений для списка из N элементов. Бинарный поиск действует умнее: проверяет средний элемент одним IF и, в зависимости от того, оказался он больше или меньше искомого, отбрасывает половину оставшегося списка, даже не заглядывая в неё.

Каждое сравнение уменьшает вдвое то, что осталось, — это формула удвоения из главы 2, только в обратную сторону, так что худший случай — это просто сколько раз можно поделить N пополам, прежде чем дойти до 1: log₂ N, округлённый вверх. Подвиньте размер списка ниже и посмотрите, как разрыв между «проверить всё» и «проверить с умом» становится огромным.

БИНАРНЫЙ ПОИСК, ХУДШИЙ СЛУЧАЙ
comparisons = ⌈log₂ N⌉
Глава 2 спрашивала, сколько состояний дают n бит (2ⁿ). Это тот же вопрос, но наоборот: сколько делений пополам нужно, чтобы дойти от N до 1.
РАЗМЕР СПИСКА N1,000
CH.12 / 13 — ОТ ЛОГИЧЕСКИХ ЭЛЕМЕНТОВ К ПРОЦЕССОРУ

Всё, что было выше, — уже компьютер. Ему просто нужны тактовый генератор и память.

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

А ветвление из главы 5 в «железе» превращается в мультиплексор: элемент, который смотрит на условие и переключает, какой из двух проводов реально дойдёт до следующего регистра. Каждая инструкция if, когда-либо выполненная любой программой, в конце концов компилируется именно в это — тикающее на чьём-то тактовом генераторе.

ТАКТОВАЯ ЧАСТОТА
f = 1 / T
Генератор на 1 ГГц тикает миллиард раз в секунду — миллиард шансов в секунду для обновления каждого регистра.
ТАКТОВАЯ ЧАСТОТА, f1.00 GHz
1.00 ns
ПЕРИОД МЕЖДУ ТАКТАМИ (T = 1 / f)
CH.13 / 13 — ТРАССИРОВКА ПРОГРАММЫ: ОТ ВХОДА ДО ПОСЛЕДСТВИЯ

Читайте программу так, как это делает компьютер: одна строка — одно следствие, шаг за шагом

Все главы этой страницы теперь уместились в одной небольшой программе — входные данные, И, ветвление, вычитание, накопительная сумма. Задайте два входных значения ниже, затем нажимайте STEP, чтобы проходить программу по одной строке и видеть, как в реальном времени меняется каждая переменная.

В этом и есть весь смысл умения читать логику, а не просто ей доверять: при любых начальных условиях вы теперь можете предсказать, строка за строкой, ничего не запуская, что именно окажется на выходе.

ВЫВОД ПРОГРАММЫ—

«Цель настоящего трактата — исследовать фундаментальные законы тех операций разума, посредством которых совершается рассуждение».

ДЖОРДЖ БУЛЬ, «ИССЛЕДОВАНИЕ ЗАКОНОВ МЫШЛЕНИЯ», 1854