"Возможно, самая красивая система счисления — это сбалансированная троичная" — Дональд Е. Кнут, Искусство программирования, Издание 2.
Многие знают, что компьютеры хранят данные и работают с ними с помощью двоичной системы счисления. Одно из главных объяснений этому можно найти в схеме современных компьютеров, которые состоят из миллиардов простых и массово производимых транзисторов и конденсаторов, которые могут вместе представлять два состояния: высокое напряжение (1
) и низкое напряжение (0
).
Такая конструкция сегодня настолько распространена, что трудно себе представить, как компьютеры могут работать иначе. Но, в Советской России 50-х годов они работали иначе. Если вы вдруг не слышали про такое, загуглите "Сетунь" — сбалансированный трехкомпонентный компьютер, разработанный в 1958 году небольшой группой во главе с Брусенцовым, в МГУ.
Перед тем, как говорить о Брусенцове и Сетуни, давайте я немного объясню вам троичную сбалансированную систему счисления.
Сбалансированная троичность
Тернарная или троичная — это система счисления, в которой есть три вероятных значения: 0
, 1
и 2
. В её сбалансированной версии существуют три вероятности -1
, 0
и +1
, часто упрощённые до -
, 0
и +
соответственно.
В такой форме троичные значения подразумеваются в виде "централизованных" вокруг средней точки 0
. Применяются те же правила, как и к любой другой системе счисления: самый правый символ, R
, имеет собственное значение, а каждый последующий символ имеет значение, умноженное на основание B
, возведенное в степень равную расстоянию D
от R
.
Эмм, давайте я просто приведу пример. Давайте запишем 114
:
+++-0 = (1 * 3^4) + (1 * 3^3) + (1 * 3^2) + (-1 * 3^1) + 0
= 81 + 27 + 9 + -3
= 114
И в бинарной (двоичной):
1110010 = (1 * 2^6) + (1 * 2^5) + (1 * 2^4) + 0 + 0 + (1 * 2^1) + 0
= 64 + 32 + 16 + 2
= 114
И, для уверенности, те же правила, применённые при десятичной системе счисления:
114 = (1 * 10^2) + (1 * 10^1) + (4 * 10^0)
= 100 + 10 + 4
= 114
Круто?
Что если мы хотим представить -114
? В двоичной и десятичной системах нам понадобится использовать новый символ: знак (sign). В основной памяти двоичного компьютера это осуществляется либо через хранение ведущего бита, указание знака или значительное уменьшение количества чисел, которые мы можем представить1. Именно по этой причине мы говорим о signed
и unsigned
в языках программирования.
Но в симметричной троичной системе, как мы узнаем позже, чтобы представить обратную величину числа (инвертированное число), нам просто нужно поменять все "+" на "-" и наоборот. Нам не нужна какая-то дополнительная информация, чтобы указать знак!
Вот смотрите:
---+0 = (-1 * 3^4) + (-1 * 3^3) + (-1 * 3^2) + (1 * 3^1) + 0
= -81 + -27 + -9 + 3
= -114
Чуть позже мы увидим, что это и несколько других свойств сбалансированной троичной системы дают нам некоторые очень интересные вычислительные преимущества. Но сейчас, давайте вернемся к разговору о компьютере Сетунь.
Рождение Сетуни
В конце 50-х годов в мире компьютеров был захватывающий период: Натаниэль Рочестер и его команда в IBM недавно разработали первый серийно выпускаемый компьютер с хранящейся в памяти программой, так называемый «современный» компьютер IBM 701. Джон Бэкус со своей командой изобрели FORTRAN, первый язык программирования высокого уровня, который обрёл широкое применение. И, пожалуй, самое главное — начали развиваться первые целиком транзисторные компьютеры, такие как TX-0 и Philco Transac S-2000. Было задано направление для разработки двоичных компьютеров, которые позже стали доминировать.
Но это было в Северной Америке.
В то же время в России группа математиков и инженеров под руководством Брусенцова и его коллеги Сергея Соболева разрабатывает другие компьютерные системы2. Брусенцов и его коллеги исследуют множество западных компьютеров и технологических достижений, и осмысливают применение транзисторов для представления двоичных данных. Но давайте вспомним, что это СССР — транзисторы не так легко доступны за железным занавесом. А электронные лампы трубки одинаково отстойны как в России, так и на Западе!
Поэтому Брусенцов разрабатывает базовый элемент из миниатюрных ферритовых сердечников и полупроводниковых диодов, который способен работать как регулируемый трансформатор тока. Он оказывается эффективной базой для реализации троичной логики3. Было установлено, что эти элементы, по сравнению с их двоичными аналогами, обеспечивают более высокую скорость и надежность и требуют меньше мощности для работы.
Команда из десяти человек буквально построила Сетунь из ничего, работая в небольшой комнате, заполненной лабораторными столами (которые они же сами и построили!). Каждое утро члены команды собирали пять простых машинных элементов. Они брали ферритовые сердечники и, используя обычную швейную иглу, наматывали на каждый по 52 мотка проволоки. Ядра затем передавали техникам, которые завершали процесс сборки и монтировали их в блоки.
Троичная логика была реализована через объединение двух таких ферритовых элементов и подключения их таким образом, что они моделировали три устойчивых состояния. Этот подход был успешным, но количество необходимых элементов не сокращалось, поскольку в действительности два ферритовых сердечника могут потенциально представлять собой два двоичных бита, что в итоге даёт больший объём информации (2 ^ 2), чем один троичный "трит" (3 ^ 1), Печально, но хотя бы потребляемая мощность была снижена!
Сетунь оперирует числами до 18 тритов, то есть один трит может моделировать любое число между -387 420 489
и 387 420 489
. Двоичному компьютеру требуется как минимум 29 битов для достижения такой мощности.
Разработка Сетуни длилась два года, несмотря на то, что система была способна производить операции уже через десять дней с начала испытаний, а в то время подобное было беспрецедентным. Всего было выпущено около 50 машин. И хотя компьютеры Сетунь безотказно работали в течение многих лет в экстремальных российских климатических условиях, проект разрывали противоречия.
В большей степени из-за неспособности завода-изготовителя оправдать массовое производство того, что они расценивали как дешёвую область науки и "плод университетской фантазии". Думаю, можно с уверенностью предположить, что Россия тогда просто была не готова понять потенциальную важность вычислительных машин. В конце концов, машины Сетунь были заменены двоичными аналогами, которые справлялись с вычислениями с той же эффективностью, но стоимость эксплуатации была выше чем в два раза!
Что же особенного в тернарной системе?
Как я уже рассказал, в ней нет необходимости хранить ведущий бит, точнее трит, чтобы указывать знак. А значит, нет понятия целых чисел со знаком или без знака — всё это просто целое число. Таким образом, вычитание достигается простым инвертированием операнда и применением сложения (которое реализуется аналогично компьютерам с двоичной системой). Эта плюс-минус консистенция также может сократить количество переносов, которые требуются для операций умножения.
Ещё одна полезная черта сбалансированной троичной системы (или любой симметричной системы счисления, раз на то пошло) это вероятность реализовать округление чисел с плавающей точкой, явным выделением целой части числа, что даёт возможность упрощённой реализации деления. Это благодаря тому как троичная система выводит дробную часть действительных чисел.
Давайте я приведу простой пример. Перевод в код числа 0.2
выглядит следующим образом:
0.+--+ = 0 + (1 * (3^-1)) + (-1 * (3^-2)) + (-1 * (3^-3)) + (1 * (3^-4))
= 0.33 + -0.11 + -0.03 + 0.01
= 0.2
И для записи 0.8
нужно начать с + в старшем разряде, а затем просто инвертировать дробную часть (например, 1 + -0,2):
+.-++- = 1 + (-1 * (3^-1)) + (1 * (3^-2)) + (1 * (3^-3)) + (-1 * (3^-4))
= 1 + -0.33 + 0.11 + 0.03 + -0.01
= 0.8
Выше видно, что выделение целой части тритов справа от поразрядной точки эквивалентно округлению: 0,2 становится нулём, а 0,8 становится единицей. Круто!
Программирование с тритами и трайтами!
Ок, возвращаемся к Сетуни в последний раз. В конце 60-х Брусенцов разработал более современную машину "Сетунь-70", которая воплотила тернарность более чётко. Было введено понятие "трайт", который состоял из 6 тритов (примерно 9,5 битов). Компьютер Сетунь-70 был стековым, и поэтому вместо машинных инструкций, которые намеренно назвали регистрами для ввода и вывода, все операции выполнялись в двух стеках — одном для операндов (вход) и одном для возвращаемых значений (выход). Для того, чтобы приспособить этот дизайн, машинные инструкции были написаны в обратной бесскобочной нотации (обратной польской нотации или постфиксной записи).
В конце 70-х годов, Брусенцов и несколько его учеников разработали язык программирования для Сетунь-70, который назвали Диалоговая система структурированного программирования (ДССП). Проводя своё исследование4, я заметил, что это стек-ориентированный язык (что, правда, совсем не удивительно), аналогичный Forth и использует обратную польскую нотацию. Это позволяет писать программы на языке относительно высокого уровня, но продолжать чувствовать себя "низкоуровнево". Настолько, что у его авторов было следующее сообщение:
ДССП не был изобретен. Он был открыт. Поэтому у языка нет версий, только расширения.
Рассмотрим программу на ДССП, которая складывает группу цифр:
1 2 3 4 DEEP 1- DO +
Давайте попробуем разложить её. В первой колонке у нас команда, во второй — состояние компьютера после выполнения (стека операндов), а в третьей я даю объяснение:
1 [1] Добавить 1 в стек.
2 [2 1] Добавить 2 в стек.
3 [3 2 1] Добавить 3 в стек.
4 [4 3 2 1] Добавить 4 в стек.
DEEP [4 4 3 2 1] Добавить "глубину стека" (4) в стек.
1- [-1 4 4 3 2 1] Добавить -1 в стек.
DO [4 3 2 1] Начать цикл, удалить два элемента из стека. Для управления циклом первый элемент применяется ко второму пока не получится 0.
+ [] Применить оператор "+" до завершения цикла,
каждый раз удаляя верхний элемент из стека операндов, применяя + и добавляя вывод в стек возвратов.
По окончанию исполнения, стек операндов будет пустым, а в стеке возвратов будет [10]
.
О ДССП подробней написано на сайте Ивана Тихонова (авторы Сидоров С.А. и Шумаков М.Н.).
Будущее
Развитие сбалансированных тернарных компьютеров практически перешло в небольшую сноску в анналах компьютерной истории. И в то время, как исследование клеток памяти, способных эффективно представлять три различных состояния было незначительным, некоторые достижения в этой области всё же были.
А именно, японские исследователи в конце 90 -х годов описали возможность использовать переход Джозефсона для реализации троичной логики. Этого можно было достичь за счет циркуляции сверхпроводящих токов — положительного (по часовой), отрицательного (против часовой стрелки), или нулевого. Они обнаружили, что это даёт ячейкам памяти "высокоскоростную способность вычислений, низкое энергопотребление и очень простую конструкцию с меньшим количеством элементов, благодаря тернарной операции".
Но я не думаю, что в ближайшем будущем вы часто будете сталкиваться с понятием сбалансированного тернарного компьютера. И что ДССП станет прорывом у агрессивных поклонников языков программирования — тоже. Но я считаю, что из прошлого можно извлечь много мудрых решений5.
(Перевод Наталии Басс)
Сноски:
- Это зависит от того, как конкретная машина представляет числа. Дополнительный код — это представление чисел в десятичной системе счисления, которое даёт возможность представить от
-((2^n) / 2)
до((2^n) / 2) - 1
вn
битах.
2) Хотя компьютер Сетунь был первым электронным устройством, использовавшим для работы тернарную систему, стоит отметить, что идея использования такой системы в вычислительных устройствах впервые была популяризована более 100 лет назад. В 1840 году Томас Фаулер построил вычислительную машину целиком из дерева, и она работала с данными, используя тернарную систему.
Более точное описание можно найти на сайте российского компьютерного музея.
Справочный материал для ДССП на английском языке не слишком доступен, поэтому я предупреждаю, что мои знания ограничены и могут содержать догадки.
Мой собственный вклад можно увидеть на computerpionee.rs.
- Изображение в статье взято с сайта Московского суперкомпьютерного комплекса МГУ, на нём одна из машин Сетунь в работе.