тм, предназначенной для аренды, то покажет себя склонным к допущению катастрофических просчетов, к которым неприменима никакая форма страхования), но даже механизм, способный выполнять базовые вычисления, станет великолепным подспорьем во многих делах.
И пусть настоящий ИИ отстоит от вас на поколения, машины, которые вы построите для того, чтобы безошибочно считать, преобразуют общество, особенно когда вы научите эти машины совершать операции в сотни тысяч раз быстрее, чем могут люди. Нам вовсе не нужно сообщать вам об этом, поскольку вы выросли в окружении компьютеров. Вы знаете, насколько они полезны, продуктивны, многосторонни и вообще удивительны.
А теперь мы покажем, как создать их с нуля.
Какую разновидность чисел ваш компьютер будет использовать, и что он будет с ними делать
Вы собираетесь использовать двоичную систему исчисления для компьютера по двум причинам: вы придумали их еще в разделе 3.3, а кроме того, это облегчает процесс, поскольку оставляет в вашем распоряжении всего два возможных значения: 0 и 1[237]. Теперь осталось только придумать, что ваш компьютер будет делать с этими цифрами. Идеальная ситуация подразумевает, что наша машина может их складывать, отнимать, делить и умножать, но нужно ли на самом деле все это?
Другими словами, какой минимальный набор возможных действий для вычисляющей машины? Так получается, что у компьютера нет технической потребности знать, как умножать, поскольку любое умножение можно представить в виде повторяющегося сложения: 10 умножить на 5 то же самое, что добавить 10 к самому себе 5 раз.
Поэтому умножение заменяем сложением:
x × y = x, прибавленный к самому себе y раз
Вычитание мы убираем тем же самым образом: 10 минус 5 равно 10 плюс –5 (отрицательное число).
Поэтому вычитание тоже заменяем сложением:
x – у = x + (—y)
И да, деление тоже можно заменить сложением.
Если мы делим 10 на 2, то мы пытаемся узнать, сколько раз 2 умещается в 10.
Можно рассчитать это, прибавляя 2 к самому себе (как мы делали при умножении), но в этот раз отслеживая, сколько двоек мы добавили, пока не добрались до нужного значения. 2 + 2 +2 + 2+ 2 = 10, то есть пять двоек, поэтому 10 разделить на 2 будет 5. Подобная техника работает даже с числами, которые нельзя разделить без остатка: необходимо добавлять до тех пор, пока следующее добавление не приведет вас за пределы числа, в котором вы заинтересованы, а то, что при этом останется, как раз и будет остатком[238].
Отсюда:
x / y = y добавляется к себе столько раз, чтобы получился x, а потом мы считаем число добавлений
Таким образом, четыре базо вые математические операции – сложение, вычитание, деление и умножение – можно свести к одной, к сложению. Поэтому, чтобы изготовить компьютер, вам нужно построить машину, способную складывать числа.
Разве это не круто, а?
О чем вообще речь и как можно говорить о сложении, если я даже не знаю, как работают компьютеры?
Прежде чем вы попытаетесь изобрести машину для сложения, давайте вернемся немного назад и вспомним пропозициональное исчисление, которое вы придумали в главе 10.13.1. Там вы определили оператор «не», означающий «противоположное тому, что говорится в утверждении». Так что если у нас есть утверждение p, которое истинно, то «не p» (или ¬p) будет, следовательно, ложным.
Что произойдет, если заменить «истинно» на «1», а ложно на «0»?
Ну, у вас есть таблица истинности для p и ¬p, которая выглядит подобным образом (табл. 19)…
Таблица 19. Таблица истинности для p и ¬p
…и которую можно превратить в список ожидаемых входных и выходных состояний бинарной машины – мы называем их «ячейками», – выглядящий следующим образом (табл. 20).
Таблица 20. Узрите же, ибо это первое в мире представление НЕТ-ячейки
Любая машина, получившая определенное значение на входе, выдаст столь же определенное значение на выходе. И совершенно не важно, как этот результат будет получен, что происходит внутри, главное, что она функционирует как НЕТ-ячейка: 1 на входе значит 0 на выходе и наоборот.
Ее можно даже нарисовать в виде схемы (рис. 62).
Рис. 62. Представление НЕТ-ячейки в графическом виде
К этому моменту у вас еще нет ни малейшего представления, как построить эту НЕТ-машину, но по меньшей мере вы знаете, что она предположительно должна делать. Поскольку же вы вовсе не обязаны «создать эту чертову штуку прямо сейчас», то мы можем рассмотреть и другие операции.
Вспомним логический оператор, который вы определили как «и» (или ∧) и который подразумевает, что оба аргумента должны быть истинными для того, чтобы утверждение в целом являлось истинным. Другими словами, «(p ∧ q)» будет истинным только в том случае, если истинны и p, и q, и ложным в любой другой ситуации.
Вот таблица истинности, которая показывает это наглядным образом (табл. 21).
Таблица 21. Таблица истинности для p ∧ q
И точно так же, как и в случае с «не», необходимо трансформировать «истинно» и «ложно» в единицы и нули, чтобы создать первую в мире И-ячейку, которую мы представим следующим образом (табл. 22, рис. 63).
Таблица 22. Входы и выходы для И-ячейки
Единственная деталь головоломки, которой нам не хватает, – это «или», нечто противоположное «и».
Операция «или» между p и q символизируется так (p ∨ q), и «(p ∨ q)» будет истинным в случае, если либо p либо q истинно.
Рис. 63. Представление И-ячейки в графическом виде
Таблица истинности для ИЛИ-ячейки выглядит следующим образом (табл. 23, рис. 64).
Таблица 23. Входы и выходы для ИЛИ-ячейки
Рис. 64. ИЛИ-ячейка
Три базовые ячейки можно использовать для того, чтобы сконструировать более сложные. Например, поставьте НЕТ-ячейку после И-ячейки, и у вас получится НЕТИ-ячейка, выглядящая следующим образом (табл. 24, рис. 65).
Таблица 24. Входы и выходы для НЕТИ-ячейки
Рис. 65. Полная НЕТИ-ячейка
С целью сохранения времени мы не рисуем НЕТ-ячейку и И-ячейку вместе, мы совмещаем их в одном изображении, вот так (рис. 66).
Рис. 66. Упрощенная НЕТИ-ячейка
НЕТИ-ячейка функционирует точно так же, как НЕТИ-ячейка, которую мы нарисовали сначала, но ее можно изобразить быстрее.
И мы можем продолжить, комбинируя разные ячейки, используя НЕТИ-ячейку, ИЛИ-ячейку и И-ячейку, чтобы создать новую ячейку, которая даст на выходе 1, если и только если на одном из входов есть 1. Любой другой вариант, и на выходе будет 0. Подобная ячейка именуется «эксклюзивное или» (ЭИЛИ), и ниже показано, как ее создать (рис. 67, табл. 25).
Рис. 67. Полная ЭИЛИ-ячейка
Таблица 25. Таблица истинности, доказывающая, что вы можете получить ЭИЛИ-ячейку из НЕТИ-ячейки, ИЛИ-ячейки и И-ячейки
И точно так же, как и в предыдущем случае, мы дадим этой ячейке собственный символ (рис. 68).
Рис. 68. Упрощенная ЭИЛИ-ячейка
Забавный факт: кроме НЕТИ-ячейки и ЭИЛИ-ячейки, которые вы только что придумали, вы можете на самом деле сконструировать ячейку, дающую любой возможный набор выходных данных, используя только И-ячейку, ИЛИ-ячейку и НЕТ-ячейку, с которых вы начинали[239].
Итак, прекрасно, что я изобрел все эти ячейки, но ни одна из них ничего не складывает, что за дела?
Правильно.
Ну, давайте определим, как должна выглядеть я чейка, способная складывать. Попробуем начать с оснований – с прибавления друг к другу бинарных чисел, что позволит нам создать клево выглядящую таблицу истинности для всех возможных исходов (табл. 26).
Таблица 26. Невероятно, но не первый раз в этой книге мы объясняем, что 1 + 1 = 2
Фишка в том, что бинарная система имеет дело с нулями и единицами, и вы получили бинарное 10 (то есть 2) в одном из вариантов. Так что давайте разобьем наш канал выхода на два, чтобы каждый представлял один бинарный разряд, вот так (табл. 27).
Таблица 27. Как складывать до двух в бинарном отображении
Теперь у нас есть два входа (представляющих два одноразрядных бинарных числа, которые вы хотите сложить) и два выхода (представляющих двухразрядное решение, снова выраженное бинарным образом). Мы поименовали их a и b, и вместе они кодируют то, к чему приводит сложение разрядов на входе.
Все, что нам теперь нужно, это разобраться, как сконструировать подобное с помощью тех ячеек, что уже есть в нашем распоряжении: И, ИЛИ, НЕТ, НЕТИ и ЭИЛИ[240]. Если вы посмотрите на паттерны единиц и нулей, образующиеся в a и b, то заметите, что они выглядят знакомыми: выход a идентичен тому, что получался у И-ячейки (p ∧ q), а b прекрасно соотносится с ЭИЛИ-ячейкой.
А это делает процесс конструирования очень простым, вам всего лишь нужно соединить входы с И-ячейкой и с отдельной ЭИЛИ-ячейкой вот таким образом, и ваша складывающая машина окажется готова (рис. 69).
Рис. 69. Складывающая машина
Имея ее в распоряжении, вы определили операцию, которую должна совершить машина, чтобы прибавить 1 к 1. Теперь, когда вы уже знаете, чему равно 1 + 1[241], эта машина, называемая «одноразрядный сумматор с двумя входами», выглядит совершенно бесполезной.
Однако давайте еще раз посмотрим, как работает сложение.