От золотого сечения до троичности Брусенцова: одно семейство числовых форматов от 2 до 1024 бит — и что я в нём реально измерил
Памяти Николая Петровича Брусенцова (7 февраля 1925 — 4 декабря 2014).
Эту статью я посвящаю памяти человека, который поверил в троичность тогда, когда весь мир уже выбрал двойку. Главный конструктор «Сетуни» — первой в мире электронной троичной ЭВМ, участник Великой Отечественной войны (радист-разведчик с 1943 года), кандидат технических наук, он с 1953 по 2014 год работал в МГУ и до последних дней заведовал лабораторией троичной информатики (ВМК МГУ; Брусенцов, Рувики). В феврале 2025 года ему исполнилось бы 100 лет (ВМК МГУ, к 100-летию).
Он оказался прав: шестьдесят лет спустя троичность вернулась — в весах больших языковых моделей. Этот текст — о том, почему его идея была не ошибкой, а просто опережением времени.
Все мы привыкли, что чисел с плавающей точкой «бывает несколько»: float32, float16, bfloat16, в последние пару лет — FP8 и совсем экзотика вроде MXFP4. Каждый из них — это компромисс между диапазоном и точностью, который кто-то однажды зафиксировал руками: столько-то бит на экспоненту, столько-то на мантиссу.
А что если не выбирать сплит руками, а вывести его из одной математической константы — золотого сечения? Так появился GoldenFloat: семейство форматов, где разбиение «экспонента : мантисса» на каждой ступеньке задаётся одним и тем же законом, привязанным к тождеству φ² + φ⁻² = 3. А на самом нижнем, 2-битном пределе этого семейства неожиданно оказывается старая знакомая — балансная троичность {−, 0, +}, та самая, на которой в 1958 году в МГУ построили легендарную «Сетунь».
Эта статья — про обе вещи сразу и про их связь. Сначала про φ-лестницу форматов и единственное, что в ней измерено end-to-end. Потом про «Сетунь», Брусенцова и красоту балансной троичности. И в конце — про то, как троичность вернулась в эпоху больших языковых моделей (BitNet) и как она садится в φ-семейство как его нижняя ступень. Честно, со всеми статус-метками: что измерено, что только спецификация, а что вообще не моё изобретение.
Сразу честная рамка, потому что без неё статья превратилась бы в рекламу: end-to-end я проверил пока только один формат семейства — GF16. Всё остальное — это спецификация и, местами, RTL. Оптимальность всего семейства — открытый вопрос.
Препринт по GoldenFloat: arXiv:2606.05017.
Оглавление
Откуда вообще берётся «сплит» в float
Любое двоичное число с плавающей точкой шириной N бит — это три поля: знак S, экспонента E и мантисса M, причём S + E + M = N. Например, классический float16 — это 1+5+10, а bfloat16 — 1+8+7. Разница только в том, сколько бит отдали под диапазон (экспонента), а сколько под точность (мантисса).
Эти сплиты исторически выбирались под задачу. bfloat16 «украл» три бита у мантиссы и отдал их экспоненте, чтобы покрыть тот же диапазон, что и float32 — для обучения нейросетей диапазон оказался важнее точности. То есть никакого «закона» тут нет: есть инженерные решения, каждое со своей историей.
Вопрос, с которого всё началось: а можно ли выбрать сплит не вкусовым решением, а единым правилом, одинаковым для всех ширин — от пары бит до тысячи?
Почему именно золотое сечение
Золотое сечение φ = (1+√5)/2 ≈ 1,618 знаменито своим «самоподобием»: φ² = φ + 1. Из него же следует менее известное, но очень удобное тождество:
φ² + φ⁻² = 3
Это не нумерология и не магия — это элементарно проверяемое равенство (подставьте φ и посчитайте). Именно оно — якорь всей конструкции. В терминах чисел Люка оно записывается как L₂ = 3, а в «железе» превращается в конкретную константу-семя dot4 = 0x47C0, которая зашита в Verilog как 16'h47C0.
Идея сплита: выбирать соотношение числа бит экспоненты к числу бит мантиссы так, чтобы оно стремилось к 1/φ ≈ 0,618. Нормативная формула для ступеньки шириной N выглядит так:
phi = (1 + 5 ** 0.5) / 2 # 1.6180339887...e = round((N - 1) / phi**2) # бит экспонентыm = N - 1 - e # бит мантиссыbias = 2 ** (e - 1) - 1 # смещение экспоненты
Здесь N-1 — это все биты, кроме знакового. Один и тот же код порождает весь «лестничный» ряд форматов, не подбирая ничего руками.
Один закон на всю лестницу форматов
Если прогнать формулу по ширинам, получается семейство, которое я называю лестницей GF. Вот несколько характерных ступенек и то, насколько их сплит близок к идеальному 1/φ:
|
Формат |
Сплит (S+E+M) |
Бит |
E/M |
Близость к 1/φ |
Статус |
|---|---|---|---|---|---|
|
GF4 |
1+1+2 |
4 |
0,500 |
0,118 |
спека + RTL |
|
GF8 |
1+3+4 |
8 |
0,750 |
0,132 |
спека + RTL |
|
GF16 |
1+6+9 |
16 |
0,667 |
0,049 |
проверен e2e |
|
GF32 |
1+12+19 |
32 |
0,632 |
0,014 |
спека + RTL |
|
GF64 |
1+24+39 |
64 |
0,615 |
0,003 |
спека + RTL |
|
GF256 |
1+97+158 |
256 |
0,614 |
0,004 |
спека + RTL |
|
GF1024 |
1+391+632 |
1024 |
0,619 |
0,0006 |
только спека |
Что тут важно и честно отметить: «близость к 1/φ» — это не показатель качества формата на реальных данных. Это просто метрика того, насколько аккуратно сплит лёг на целочисленную сетку бит. Чем шире формат, тем плотнее сетка и тем точнее можно попасть в идеал — поэтому у GF1024 близость лучшая, но это совершенно не значит, что GF1024 где-то «лучше всех». Это значит ровно одно: правило применимо на всём диапазоне ширин.
Аккуратная формулировка, которую я готов защищать (и она помечена как открытая гипотеза, а не доказанный факт):
Мне не известно другое опубликованное семейство float-форматов, у которого сплит E:M по всей лестнице от 2 до 256 бит порождался бы одним замкнутым правилом.
Это утверждение про методологию, а не про производительность. И формулировка именно «мне не известно», а не «единственное в мире» — потому что доказать отсутствие чего-либо нельзя.
Lucas-точные аккумуляторы: где φ ведёт себя как целое
Есть один по-настоящему приятный бонус золотого якоря. Степени φ²ⁿ + φ⁻²ⁿ — это всегда целые числа (это числа Люка с чётным индексом). То есть когда вы накапливаете суммы определённого вида, результат можно держать в точной целочисленной арифметике, без накопления ошибки округления.
Это свойство я проверил формально: целочисленный аккумулятор Lucas-EII прогнан для n = 1 … 256 с точностью 500 знаков и доказан в Coq. Для обычного float такое «бесплатное» отсутствие дрейфа округления — редкость, и именно тут золотое сечение даёт не эстетику, а инженерную пользу.
Что измерено на GF16 (и почему именно он)
GF16 — единственная ступенька, доведённая до конца: Rust-референс, Verilog-реализация и тестбенч на FPGA Artix-7, 35 из 35 тестов проходят, рабочая частота 323 МГц. Это «замороженный» якорь семейства — именно его сплит 1+6+9 служит эталоном, к которому привязана нормативная формула.
Теперь измерения. В сравнении на обучении байтового языкового моделирования (метрика val_bpb, меньше — лучше) картина такая:
|
Формат |
val_bpb |
Честное чтение |
|---|---|---|
|
float32 |
2,5414 |
полноточностный базлайн |
|
float16 |
2,5501 |
лучший 16-битный в этом прогоне |
|
GF16 |
2,5725 |
+0,031 к f32; обходит bfloat16 |
|
bfloat16 |
2,6135 |
худший из 16-битной тройки |
Что это значит на человеческом языке: GF16 играет в одной лиге с float16 и измеримо обходит bfloat16 на этой задаче. Но float16 его всё-таки слегка опережает. Это ограниченный эмпирический результат на одной задаче, а не «GF16 лучше всех».
И сразу честная рамка, чтобы никто не принял это за больше, чем оно есть. End-to-end измерен пока только GF16; остальные ступени — это спецификация и, где-то, RTL, без бенчмарков. Красивый сплит из 1/φ не означает оптимальности — известна работа Daubechies et al. (Golden Ratio Encoder), где φ не единственное «хорошее» основание; реальный плюс скромнее — «безмультипликаторность» (из φ² = φ + 1 множитель усиления схлопывается в единицу). Сопутствующий чип-каталог Corona — submission-ready дизайн (RTL + GDS + формальные доказательства + cocotb), проверенный в симуляции, а не изготовленный кристалл: проверено формально и в sim, кремний — впереди. Всё это я держу под явными статус-метками (Verified / Empirical fit / Open conjecture).
А теперь — самая красивая часть. У этой φ-лестницы есть не только верх (GF1024), но и низ. И на самом низу, на 2-битном пределе, обнаруживается то, что построили в железе ещё 68 лет назад.
Сетунь: машина, которой не дали жить
В 1958 году в вычислительном центре МГУ собрали машину, которая по меркам тогдашней (и сегодняшней) индустрии была еретической: она считала не в двоичном коде, а в троичном. Машина называлась «Сетунь», её главным конструктором был Николай Петрович Брусенцов, а идейным вдохновителем — академик С. Л. Соболев. Это была первая в мире электронная троичная ЭВМ — и, как часто бывает с красивыми идеями, она же оказалась почти единственной.
История начинается в начале 1956 года, когда в МГУ под началом Соболева взялись за создание небольшой ЭВМ — простой в освоении, надёжной и дешёвой. Год ушёл на изучение существующих машин, и по итогам команда приняла нестандартное решение: строить не на двоичном, а на троичном коде (Брусенцов, Рамиль Альварес, SoRuCom 2006).
К концу 1958 года «Сетунь» была собрана и начала работать; к концу 1959-го готова система программирования, а к апрелю 1960-го машина прошла межведомственные испытания (там же). Несколько сухих, но красноречивых цифр из той же статьи Брусенцова:
-
всего 24 одноадресные команды — минималистичный набор;
-
оперативная память — 162 девятитритные ячейки (3 страницы по 54);
-
регистры на 18 и 9 тритов, индексный регистр на 5 тритов;
-
около 2 тысяч элементов в машине, цена элемента — 3 рубля 50 копеек;
-
продавалась всего за 27 500 рублей.
И — что особенно впечатляет — надёжность. За первый год эксплуатации заменили всего три дефектных элемента; экспериментальный образец в вычислительном центре МГУ проработал «в абсолютно рабочем состоянии семнадцать лет непрерывной работы» (там же). Серийные машины работали в климате «от Одессы и Ашхабада до Якутска и Красноярска».
Серийное производство шло на Казанском заводе математических машин по решению Совета Министров СССР. Но, по словам Брусенцова, чиновникам из профильного ведомства троичная машина «по неизвестным причинам не понравилась», и к 1965 году производство остановили (там же). Между 1967 и 1969 годами появился преемник — «Сетунь 70» с двухстековой архитектурой, работавшая трайтами по 6 тритов и поддерживавшая идеи структурного программирования Дейкстры. Но широкой серии уже не случилось.
Что такое балансная троичность и почему она красива
Двоичный бит хранит одно из двух значений: 0 или 1. Трит хранит одно из трёх. Но «Сетунь» использовала не «несимметричную» троичность с цифрами {0, 1, 2}, а балансную (симметричную) — с цифрами {−1, 0, +1} (часто записывают как −, 0, +).
Число записывается так же позиционно, как и обычно, только вес i-й позиции равен 3ⁱ, а цифры берутся из {−1, 0, +1}. Например (значения из статьи Брусенцова): десятичное 13 — это + + +, 7 — это + − +, 6 — это + − 0, а −6 — это − + 0 (Брусенцов, SoRuCom 2006).
У балансной троичности есть несколько свойств, которые ценили и Брусенцов, и до него — Клод Шеннон (отметивший преимущества системы ещё в 1950 году), и позже Дональд Кнут, назвавший её «возможно, изящнейшей» системой счисления (Брусенцов, SoRuCom 2006; Ternary computer, Wikipedia):
-
Знак — это просто старший ненулевой трит. Отдельный «знаковый бит» не нужен, знак числа определяется естественно.
-
Смена знака — инверсия разрядов. Каждый
+становится−и наоборот. Никакого дополнительного кода, как в двоичном. -
Округление — это просто отбрасывание младших разрядов (оно же оптимальное округление к ближайшему).
-
Единая операция сдвига и единообразное кодирование чисел.
Есть и теоретико-информационный аргумент, который любят повторять: самым «экономным» по плотности хранения было бы основание e ≈ 2,718; из целых оснований к нему ближе всего тройка, а не двойка (Исследование элементов троичной логики, Молодой учёный). То есть троичность — не каприз, а попытка попасть в математически выгодную точку.
Важная честная оговорка: «экономнее по основанию» не значит «быстрее и дешевле в кремнии прямо сейчас». Реальный мир выбрал двойку по совокупности инженерных и экономических причин — об этом дальше.
Упущенный шанс: почему победил двоичный код
Если троичность так красива, почему мир считает в нулях и единицах? Коротко — не из-за математики, а из-за инженерии и инерции экосистемы:
-
Двоичная элементная база (транзистор как переключатель «вкл/выкл») оказалась проще, дешевле и быстрее в массовом производстве. Стабильно различать два уровня напряжения легче, чем три.
-
Вокруг двойки выросла вся экосистема: память, логика, стандарты, компиляторы, целые поколения инженеров.
-
«Сетунь», при всех её достоинствах, не получила административной поддержки — и красивая ветка эволюции просто заглохла.
Это классическая история про то, как «достаточно хорошее и повсеместное» побеждает «изящное, но одинокое». Троичность не была неправильной — она была несвоевременной.
Возвращение троичности: BitNet и веса в LLM
А теперь — поворот. В эпоху огромных языковых моделей главным дефицитом стали память и энергия: веса моделей измеряются миллиардами чисел, и хранить каждое в 16 или 32 битах дорого. Возникла волна квантизации — представлять веса всё более грубо, лишь бы модель не разваливалась.
И на пределе этой волны индустрия пришла ровно к троичности. Модели семейства BitNet (Microsoft Research) используют веса, принимающие фактически три значения — {−1, 0, +1} — что даёт знаменитые «1,58 бита на вес» (log₂ 3 ≈ 1,585). Это ровно балансная троичность Брусенцова, только теперь она живёт не в ферритовых сердечниках «Сетуни», а в матрицах весов нейросети.
Смысл тот же, что шестьдесят лет назад: три состояния {−, 0, +} оказываются удачным компромиссом. Ноль позволяет «выключить» связь (разреженность), а ±1 несут знак без отдельного бита. Умножение на такой вес — это вообще не умножение, а выбор «прибавить / ничего / вычесть». Брусенцов бы оценил.
Нижняя ступень: GFTernary и TF3 (честно)
Теперь — обещанная связь между φ-лестницей и троичностью. Если у GoldenFloat есть верх (GF1024), то у него есть и самый низ — 2-битный предел. И этот предел — троичный. Но здесь я обязан быть предельно честным насчёт статуса.
В каталоге есть два разных троичных объекта, которые легко спутать:
-
GFTernary — 2-битный формат, значения которого буквально
{−φ, 0, +φ}(где φ — золотое сечение). По сути это балансная троичность Брусенцова, у которой ненулевая величина равна не единице, а φ. Это и есть нижняя ступень φ-семейства: тот же закон, доведённый до двух бит. Статус: спецификация + референс-реализация на Rust и Zig. Это не серийный чип. -
TF3 — 8-битный контейнер для хранения троичных весов нейросети (геометрия
1+3+4, как у GF8) с метаданными. Это именно контейнер хранения, а не 2-битный формат. Статус: только спецификация.
И ещё одна честная деталь про «железо». В сопутствующем чипе-каталоге Corona есть декодер формата bitnet — то есть троичные представления учтены на уровне дизайна. Но Corona — это submission-ready дизайн (RTL + GDS + формальные доказательства + cocotb-тесты), проверенный в симуляции и формально. Изготовленного и протестированного на столе кристалла нет. Поэтому никаких «доказано на кремнии» — корректная формулировка: проверено в симуляции и формально, кремний впереди.
Чего я НЕ утверждаю, и это важно:
-
Я не изобретал троичную логику — это Брусенцов и «Сетунь», а в современном виде — BitNet от Microsoft Research. Мой вклад скромнее: троичность естественно ложится в φ-семейство как его 2-битный предел, с ненулевой величиной φ вместо единицы.
-
В моих измерениях end-to-end проверен пока только 16-битный GF16 (см. таблицу выше). Троичные ступеньки семейства — это спецификация, а не измеренный результат.
То есть связь честная и неслучайная: одна и та же идея — «три состояния {−, 0, +}» — проходит через «Сетунь», через BitNet и через 2-битный предел моего φ-семейства. Но превращать это в громкие заявления я не буду; статус каждого кирпичика указан явно.
Как это потрогать руками
Препринт со всеми деталями и таблицами лежит на arXiv:2606.05017. Нормативная формула сплита приведена выше — её достаточно, чтобы воспроизвести всю лестницу форматов в десяток строк на любом языке. Соседние форматы (FP8, bf16, posit, takum и другие) я держу в открытом каталоге как союзников и контрпримеры, а не как «поверженных конкурентов» — в частности, takum (Hunhold, 2024) специально лежит рядом как честный контрпример к гипотезе о «широте как преимуществе».
Выводы
-
Сплит «экспонента : мантисса» можно не подбирать руками, а вывести из одного закона — стремления E/M к 1/φ, с якорем φ² + φ⁻² = 3. Получается единое семейство форматов на всём диапазоне ширин.
-
Золотой якорь даёт реальный инженерный бонус — Lucas-точные целочисленные аккумуляторы без дрейфа округления (проверено в Coq).
-
Из всего семейства end-to-end проверен только GF16: паритет с float16, измеримо лучше bfloat16 — но это один результат на одной задаче, не универсальная победа.
-
Внизу той же лестницы лежит троичность. «Сетунь» (1958, МГУ, Брусенцов) — первая в мире электронная троичная ЭВМ: 24 команды, ~2000 элементов, поразительная надёжность — и закрытая к 1965 году не по техническим причинам.
-
Балансная троичность
{−1, 0, +1}математически изящна (знак — старший разряд, смена знака — инверсия, округление — отбрасывание младших). Победил двоичный код — из-за простоты элементной базы и экосистемы, а не из-за «неправильности» троичности. -
В эпоху LLM троичность вернулась: BitNet b1.58 (Microsoft Research) — по сути та же балансная троичность Брусенцова в весах нейросети.
-
В моём φ-семействе троичность присутствует как GFTernary (
{−φ, 0, +φ}, спека + Rust/Zig) и TF3 (контейнер, только спека); Corona — дизайн в симуляции, не чип. Никаких «доказано на кремнии».
Если интересно, в следующий раз могу подробно разобрать Lucas-точные аккумуляторы — с кодом и тем, как именно целочисленность φ²ⁿ + φ⁻²ⁿ убирает накопление ошибки, — и чем умножение на троичный вес дешевле обычного.
Открыт к сотрудничеству с AI-лабораториями и командами
Если вы из AI-лаборатории, чип-вендора или ML-команды и вам интересно попробовать GoldenFloat (в первую очередь проверенный GF16, а также лестницу форматов, Lucas-точные аккумуляторы и троичную нижнюю ступень в духе BitNet) на своих задачах — напишите мне. Я открыт к совместной работе в любом из форматов:
-
прогнать GF16 на вашем железе или в вашем training/inference-стеке и честно сравнить с float16 / bfloat16 / FP8 на ваших данных;
-
честно сравнить троичные/низкоразрядные представления (BitNet-веса, GFTernary как 2-битный предел) на ваших задачах;
-
помочь с интеграцией форматов в ваши кернелы и инструментарий (есть Rust-референс, Verilog/FPGA-реализация и открытый каталог совместимости с бит-точными конформанс-векторами и Corona-дизайн как оракул);
-
совместно довести до измерений те ступеньки лестницы, которые пока существуют только как спецификация;
-
спонсируемое исследование или совместный технический отчёт.
Честная рамка остаётся прежней: я не обещаю «формат лучше всех». Я предлагаю воспроизводимую методологию и один измеренный результат (GF16), а дальше — смотрим на ваших задачах вместе и публикуем то, что реально получилось, со всеми статус-метками.
Пишите на admin@t27.ai — расскажите, какой у вас стек и какую задачу хотите проверить. Общение асинхронное, на английском или русском.
Об авторе. Dmitrii Vasilev, Trinity S³AI. ORCID 0009-0008-4294-6159. Препринт по GoldenFloat: arXiv:2606.05017. Связь: admin@t27.ai
ссылка на оригинал статьи https://habr.com/ru/articles/1050924/