Джордж Оруэлл. «1010001001001000.1001001000100001»
Существует ли позиционная система счисления с иррациональным основанием, в которой все натуральные числа записываются конечным числом цифр? В которой число больше единицы, не имеющее цифр после запятой, наверняка не целое и даже не рациональное? В которой 1 + 10 = 100, а 1 + 1 = 10.01?
Существует. Зовётся она системой Бергмана, или системой счисления с основанием ? (читается как «фи», это буква греческого, а не русского алфавита). Число ?, называемое также золотым числом или постоянной золотого сечения, имеет следующую формулу:
Далее по тексту я иногда буду называть её фиеричной (по аналогии с, допустим, восьмеричной) системой счисления, а иногда не буду.
Что это такое?
Фиеричная система счисления — это обычная позиционная система счисления с необычным основанием. Если в общеупотребительной десятичной системе счисления каждая цифра соответствует некоторой степени десятки (123 = 1•102 + 2•101 + 3•100), а в двоичной — некоторой степени двойки (1012 = 1•22 + 0•21 + 1•20), то в системе Бергмана, в которой, как и в двоичной, есть только цифры 0 и 1, каждая единица символизирует некоторую степень числа Ф. Например:
Откуда есть пошла?
Как нетрудно догадаться исходя из названия, система Бергмана была придумана неким Бергманом. Возможно, у вас возник вопрос, что за харизматичный бородач изображён в начале статьи. Так вот, это Джордж Бергман, матеметик-алгебраист, профессор Калифорнийского университета в Беркли. Он родился в Бруклине в 1943 году, а четырнадцать лет спустя, когда у него ещё не было ни бороды, ни докторской степени, но уже имелось воображение и интерес к абстрактной алгебре, опубликовал статью в Mathematics Magazine, в которой описал открытую им систему счисления (сам он называл её «тау-система»), её основные свойства и правила арифметических действий в ней. В своей статье он с достойной уважения скромностью признался, что «не видит никакого полезного применения для систем счисления, подобных этой, помимо развлечения и зарядки для ума». Время показало, однако, что в своей оценке он был не вполне прав. Однако о применении фиеричной системы счисления мы поговорим позднее.
Чем интересна?
Систем с иррациональным основанием, позволяющих записать любое натуральное число конечным количеством цифр, вообще говоря, бесконечно много. Например, система счисления с основанием, равным квадратному корню из двух. Если использовать лишь каждую вторую цифру (те, которые соответствуют чётным степеням основания), то ей можно пользоваться как обычной двоичной системой счисления:
Точно так же в качестве основания нам подойдут квадратный корень из трёх, кубический корень из двух… Ну, вы поняли мысль. Систем счисления, в которых почти все целые числа будут записываться бесконечной дробью, также немало. Скажу по секрету,
Строго говоря, этим свойством обладает любая система с трансцендентным основанием и достаточным набором цифр. В пи-ичной, е-ичной и даже в е-в-степени-пи-ичной системе счисления все натуральные числа, превосходящие единицу, будут записываться в виде бесконечной дроби.
Система Бергмана отличается и от первой, и от второй группы. В ней любое натуральное число, большее единицы, имеет ненулевое, но конечное количество цифр после запятой. Например:
2 = 10.01Ф
5 = 1000.1001Ф
42 = 10100010.00100001Ф
451 = 1010000001010.000100000101Ф
1984 = (см. эпиграф)
Просторечно выражаясь, это немного рвёт шаблон. Мы привыкли, что понятия «знаки после запятой» и «дробная часть» очевидным образом взаимосвязаны. Однако в фиеричной системе дробная часть может равняться нулю, а количество цифр после запятой при этом — не равняться. Более того, можно доказать, что если количество цифр после запятой равняется нулю, то во всех случаях кроме нуля и единицы ненулевая дробная часть неиллюзорно присутствует.
натуральным степеням Ф. Записав эти степени, раскрыв и сложив их, мы получим число вида a + bv5, где a и b рациональны, а b к тому же строго положительно, как сумма некоторого количества биномиальных коэффициентов, умноженных на некоторое количество пятёрок и делённых на сколько-то двоек. Очевидно, такое число не может быть рациональным, а значит, и целым.
Кроме целых чисел, конечным количеством знаков в фиеричной системе счисления записываются также числа из ?(Ф), то есть все числа вида:
Как, возможно, заметил внимательный читатель, ни в одной из фиеричных записей, приведённых выше, не было случая, когда две единицы идут подряд. Это не случайно. Как и в фибоначчиевой системе счисления, в системе Бергмана единица старшего разряда равняется сумме двух единицы помладше. Иначе говоря,
Как в неё переводить?
Для натуральных чисел Бергман предлагал следующий алгоритм: если мы знаем запись числа n, то смотрим, что у неё за цифра в нулевой позиции, перед запятой. Если там нуль, записываем туда единицу и получаем n+1. если там уже единица, то мы денормализуем запись числа, применяя к этой единице правило 100 = 11. Если при этом одна из вновь образовавшихся единиц попадает на место, уже занятое другой единицей, предварительно преобразуем её, и так далее. Затем в денормализованной записи меняем нуль на единицу и нормализуем обратно. Например:
4 = 101.01Ф = 101.0011Ф = 100.1111Ф
5 = 101.1111Ф = 110.0111Ф = 1000.0111Ф = 1000.1001Ф
Из доказательства корректности этого алгоритма (которое я оставляю на совесть читателя) следует, в частности, что любое натуральное число имеет конечное представление в фиеричной системе счисления. Я уже говорил об этом раньше, но теперь вы не обязаны верить мне на слово.
Этот алгоритм обладает достаточно грустной временной сложностью. Можно оптимизировать его следующим образом: вместо тупого прибавления единицы мы будем поочерёдно умножать на два и при необходимости прибавлять единицу (так, например, мы получаем значение числа из его двоичной записи). Однако умножение на два, оно же сложение числа с самим собой, в системе Бергмана — не вполне тривиальная операция, о чём мы поговорим чуть позже.
С другой стороны, мы можем за линейное время найти фиеричную запись числа тупо по определению. Этот алгоритм можно приблизительно описать следующим js-кодом:
const Phi = (Math.sqrt(5)+1)/2;
function toPhiBase(n){
var power = 1;
var result = "";
while(power <= n){
power *= Phi;
}
while(n > 0){
if(power == 1){
result += ".";
}
power /= Phi;
if(power <= n){
n -= power;
result += 1;
}else{
result += 0;
}
}
return result;
}
Увидев этот код, человек, знакомый с программированием, конечно, должен приуныть. В голове его должны пронестись мысли о числах с плавающей точкой, потере точности, тщетности бытия… И действительно, приведённая функция будет работать некорректно для хоть капельку большого числа, вроде того же 1984. Реализация подкачала, но это не значит, что плоха сама идея.
Если мы работаем с числами с плавающей точкой, потеря точности практически неизбежна. Но можно не работать с такими числами. Можно вести все операции в поле ?(v5) (то есть в поле, состоящем из чисел вида a + bv5, a, b ? ?). Действия над такими числами можно реализовать, используя только операции над рациональными числами. А операции над рациональными числами можно реализовать, используя только сложение, вычитание и умножение целых чисел, которые к потере точности не приводят. Короче говоря, можно написать свою маленькую символьную арифметику. А я всегда хотел её написать.
Как только я понял, насколько страдают обитатели интернета без возможности переводить числа в систему Бергмана и обратно, я немедленно наваял npm-модуль, основанный на вышеописанном подходе. Теперь каждый может самостоятельно проверить, не ошибся ли я в фиеричной записи числа 42, введя в консоль что-то типа:
npm install phibase node var PhiBase = require("phibase") Phibase.toPhiBase(42)
Те, у кого по каким-то неясным причинам не установлены node и npm, могут воспользоваться онлайн-конвертером
Кстати о переводе обратно. Тут опять же есть несколько подходов. Можно в стиле Бергмана вынимать из числа по единичке, при необходимости денормализуя его запись. Можно посчитать по определению в числах с плавающей точкой, смирившись с потерей точности (алгоритм приводить не буду, он вполне очевиден). Или, имея дело с рациональными числами, можно опять же воспользоваться «символьными» вычислениями — в моём модуле, как вы могли догадаться, используется именно этот способ.
Как в ней работать?
Краткий ответ: с трудом.
В системе Бергмана не работают классические алгоритмы сложения и вычитания. Как мы помним, 1Ф + 1Ф = 10.01Ф. Это означает, что при попытке сложения «в столбик» возникающие переносы будут идти как влево, так и вправо. Это лишает нас надежды просто взять числа с какого-то конца и складывать, перенося излишки в другой конец. Один из подходов к сложению в фиеричной системе состоит в том, что для начала мы складываем числа просто как векторы цифр (10.01 + 101.01 = 111.02), а затем как-то нормализуем запись. Оригинальный (в смысле, изначальный) подход, предложенный Бергманом, состоял в следующем: выписав числа одно над другим, денормализуем их таким образом, чтобы в одном и том же разряде не находились две единицы. После этого сложим их поразрядно (сложение нуля с единицей или нуля с нулём уже не представляет трудности для тренированного математика), затем нормализуем сумму.
Этот подход показался мне настолько забавным, что я написал небольшую игру, которая позволяет игроку ощутить всю его прелесть лично.
Умножение и деление, впрочем, реализуются более или менее стандартным образом — умножаем в столбик, делим уголком.
И на кой она нужна?
По-хорошему, этот раздел должен писать не я, а какой-нибудь суровый инженер советской закалки. Насколько мне известно, система Бергмана использовалась в некоторых АЦП. Предполагалось использовать её избыточность для большей помехоустойчивости, однако «железная» реализация такого преобразователя оказалась склонна к ошибкам, и идею отправили в ящик. Я бы с удовольствием рассказал больше, но не могу, и честно признаюсь в своей некомпетентности. Надеюсь, кто-то из читателей знает больше — в таком случае я с удовольствием размещу здесь ссылку на его содержательный комментарий.
janatem подсказывает в своих комментариях, что если добавить в систему Бергмана специальную цифру "-1", то получившаяся в результате симметричная система счисления будет обладать очень полезным свойством: возможностью параллельного поразрядного сложения. Иначе говоря, в ней можно получить некоторую цифру суммы чисел, не вычисляя для этого предыдущие. В десятичной системе счисления такое невозможно: чтобы наверняка знать, с какой цифры будет начинаться сумма 999995 + x (x — цифра), нам обязательно нужно знать значение x, несмотря на то, что эта цифра находится за пять разрядов от той, которая нас действительно интересует. Такую независимость разрядов можно использовать для радикального ускорения вычислений на определённых архитектурах.
Ах да, чуть не забыл. Ещё фиеричную систему счисления можно использовать для перемножения целых чисел. Делается это следующим образом:
- Одно из чисел переводится в фиеричную систему счисления и записывается куда-нибудь, желательно на клетчатую бумагу.
- Другое выписывается в клетку под нулевым разрядом первого числа.
- Слева от второго числа пишем произвольное третье число — вообще любое.
- Ряд из второго и третьего числа продолжаем влево и вправо таким образом, чтобы каждое число в ряду равнялось сумме двух чисел справа от него. Получается нечто вроде ряда Фибоначчи, только построенного на других начальных числах и направленного справа налево.
- Просуммируем все числа в этом ряду, над которыми написаны единицы. Эта сумма и будет искомым произведением
Шаг 1. 1 |0 |1.|0 |1 --+--+--+--+-- | | | | Шаг 2. 1 |0 |1.|0 |1 --+--+--+--+-- | |9 | | Шаг 3. 1 |0 |1.|0 |1 --+--+--+--+-- |13|9 | | Шаг 4. 1 |0 |1.|0 |1 --+--+--+--+-- 22|13|9 |4 |5 Шаг 5. 22 + 9 + 5 = 36
Если у вас плохо с умножением, но вы умеете быстро переводить числа в фиеричную систему счисления и строить фибоначчиобразные ряды, этот метод определённо для вас. Доказательство же его корректности основано на том, что при денормализации записи вверху сумма чисел под её единицами не изменится.
И это всё?
Есть ещё несколько вещей, которые я бы хотел сказать напоследок. Во-первых, если вы как следует помучили мой онлайн-конвертер, то могли заметить, что дробные числа в фиеричной системе счисления, как и в любой другой позиционной, записываются в виде периодической дроби. Доказательство этого факта основывается на делении уголком и опять же не отличается от доказательства, проведённого в системе счисления здорового человека.
Во-вторых, я вам наврал, когда говорил об «уникальном свойстве золотого сечения». Оно, конечно, уникально, но не совсем. Уравнение x2 = x + 1 имеет ещё одно решение, равное
В системе с основанием ?- (назовём её антифиеричной) сохраняются все свойства фиеричной системы, которые выводятся из тождества 100Ф = 11Ф. В частности, в ней имеют конечную запись все целые числа (причём ту же самую, что и в фиеричной системе). Это особенно забавно, потому что новое основание не только иррационально, но ещё и отрицательно и по модулю меньше единицы. Можно доказать даже следующую теорему: если число имеет одну и ту же конечную запись в фиеричной и антифиеричной системе счисления, то оно целое.
И наконец, в фиеричной системе счисления формулу числа Ф можно переписать следующим образом:
Цимес в том, что приведённая формула, если рассматривать её как уравнение, имеет единственное действительное решение. То есть её в самом деле можно использовать как определение числа Ф.
Вдумайтесь в это.
Комментарии (46)
Carduelis
31.05.2016 12:48-14Можете дать этимологию слову «фиеричный»? Или все-таки, от слова «феерия»?
P.S.: Пишу здесь, а не в ЛС, может быть я просто не знаю такого слова (через «и»).rughost
31.05.2016 13:06+4Ну так он же написал
«Далее по тексту я иногда буду называть её фиеричной (по аналогии с, допустим, восьмеричной) системой счисления, а иногда не буду.»
Просто вместо цифры название буквы подставил и все, как капитан выше подсказываетOld_Chroft
31.05.2016 14:01+7как капитан выше подсказывает
Сначала подумал про капитана Очевидность, затем поднял глаза на ник предыдущего комментатора… Нет, Флинт :-)
Интересно, а звание дважды капитана существует?
janatem
31.05.2016 13:03+9Один из самых вкусных и полезных фактов оказался за кадром. Для системы с основанием ? (кстати, для обозначения золотого сечения принято использовать малую фи, а не заглавную), а также для некоторых других избыточных систем (у которых основание меньше количества цифр) существует алгоритм сложения, обладающий поразрядным параллелизмом. Нетрудно заметить, что для традиционных систем счисления это неверно, поскольку перенос из младшего разряда может доползти до старшего, то есть старший разряд результата неизбежно зависит от всех разрядов слагаемых. Для чисел большой разрядности (скажем, 1000 и более двоичных разрядов) уже можно ставить вопрос о более эффективной, чем традиционной двоичной, аппаратной или программной реализации арифметики.
Sirion
31.05.2016 13:10для обозначения золотого сечения принято использовать малую фи, а не заглавную
Я вырос на обозначениях, где фи малое — это величина, обратная к фи большому, т.е. как в википедии.
А факт действительно крутой, мне он был неизвестен, и я сходу не могу сообразить, как этого можно добиться. Не поделитесь ссылкой?
janatem
31.05.2016 14:07+3- Гуглить по слову beta-expansion
- Серия статей за авторством Ch. Frougny, E. Pelantova, M. Svobodova, например, "Parallel addition in non-standard numeration systems"
- По-русски могу предложить свою статью http://psta.psiras.ru/read/psta2015_2_101-117.pdf (в статье ошибка, из-за которой всё заявленное работает только для рациональных оснований). В любом случае там будет полезна обзорная часть.
Sirion
31.05.2016 14:20+2А, вот оно что! Нашёл статью из второго пункта, там появляется дополнительная цифра "-1". А я уж всю голову сломал, пытаясь понять, как в оригинальной бергмановской системе организовать параллельное сложение.
Спасибо за информацию, помещу ссылку на ваш комментарий в статью.janatem
31.05.2016 15:00Хм, вообще-то, если я правильно помню, организовать параллельное сложение можно и с двумя цифрами {0,1}, главное, чтобы основание было меньше 2. Общее утверждение таково, что для существования поразрядного паралеллизма достаточно: (1) количество цифр (0, 1, ...) должно быть больше, чем основание, (2) основание должно быть алгебраическим числом (это требуется только для "точных" представлений, для интервальных вроде не обязательно) и (3) довольно причудливое условие на алгебраические сопряженные основания, которое для фи выполнено.
Sirion
31.05.2016 15:06+4Тут говорят:
When the base ? is the Golden Mean, we further refine the construction to obtain a parallel algorithm on the alphabet {?1, 0, 1}. This alphabet cannot be reduced any more.
(выделено мной).Halt
01.06.2016 09:18Интересно, как это ложится на вычислительные машины с троичной логикой. Понятно, что напрямую операции не закодировать, но с учетом полного отображения базы в трит я думаю можно получить более элегантное решение чем для двоичной логики.
Sirion
01.06.2016 10:10Насколько я успел вкурить
бамбукстатью, там в промежуточном представлении при сложении используются цифры от -2 до 2. Так что триты не спасут отца русской демократии.
grechnik
31.05.2016 14:33+3Упражнение на закрепление материала: https://projecteuler.net/problem=558.
Wesha
31.05.2016 21:03Фиеричная
Каждый раз при прочтении этого слова рука моего внутреннего граммар-наци тянется к расстрельному "вальтеру", но в следующую секунду опускается обратно ;)
Цимес в том, что приведённая формула, если рассматривать её как уравнение, имеет единственное действительное решение.
Прочитав это, мой внутренний хакер немедленно встрепенулся и задал вопрос — "раз есть действительное решение — значит, должно быть и комплексное, нельзя ли его как-нибудь в хозяйстве применить?"
Sirion
31.05.2016 21:08Применять в хозяйстве, я думаю, будет проблематично — судя по всему, комплексные решения невыразимы в радикалах. Только численные методы, только приближенное решение, только грусть…
Zenitchik
01.06.2016 11:03Нужно просто ввести мнимую цифру.
Sirion
01.06.2016 13:40Ввести, простите, куда?
Zenitchik
01.06.2016 14:51Уже писали про цифру -1, чтобы получить симметричную систему.
Я хотел написать, что чтобы получить возможность записи комплексных чисел нужно добавить ещё i и -i, но по здравому размышлению это неудачная идея.Sirion
01.06.2016 15:07+1Для записи комплексных чисел можно взять основание корень из минус фи и не париться. Но вообще изначально в этой ветке речь шла о комплексных решениях уравнения. Это, по идее, совсем другая история.
demoth
31.05.2016 22:57+1Было бы интересно на основе этой cистемы счисления сделать фиеричный эзотерический язык программирования. Возможно, получится даже сложнее Malbolge, с его троичной с/с и операцией crazy. :)
alexhap
01.06.2016 10:17жажду увидеть пару абзацев о практической полезности данной фисистемы
Sirion
01.06.2016 10:20+2Про неё можно писать хабрапосты, набирающие неплохой рейтинг, по крайней мере один раз.
Occama
01.06.2016 13:19Думаю, что и на 10.01 раза материала может хватить =) Но тут нужен какой-то совсем прошаренный инженер-математик
iPR
01.06.2016 20:02+1Неплохой рейтинг также могут набрать посты про «Pi-еричную» систему, а также конвертер из «фи-еричной» системы в «pi-еричную» согласно формуле:
luarviq
01.06.2016 13:19Интересно, для компрессии данных ее можно использовать? Ведь 100=11 в ней, а значит, можно кодировать три символа двумя.
kolpeex
01.06.2016 19:36+2Видимо, поскольку у фееричного числа может быть несколько форм, то «сжатую» информацию нельзя одназначно интерпретировать. А если исходные данные всегда в нормальной форме, то это накладывает ограничения на «несжатую» информацию.
luarviq
02.06.2016 07:09Спасибо. Прочитал оригинальную статью Бергмана, получил истинное удовольствие от красоты этой системы. Для интересующихся темой есть также отличная книга А.П. Стахов «Коды золотой пропорции» М. Радио и связь, 1984
hdfan2
02.06.2016 07:25+1> таких даже больше, их континуум
Нужно будет запомнить. Хороший эвфемизм для выражения «до х#я»
spaceproof
02.06.2016 16:23Вспомнился анекдот про то, как разделить 28 танков между между 7 ротами по 13 штук.
Ведь такая система счисления тоже должна как-то называться.Sirion
02.06.2016 16:59Тут скорее попытка ввести на множестве целых чисел альтернативную кольцевую структуру.
danSamara
07.06.2016 13:39soniq
04.06.2016 02:56Не пойму, как так получается. В двоичной системе счисления две цифры, в троичной — три, в шестнадцатеричной — шестнадцать. Это мне понятно, и вроде этому меня и учили. А тут, мало того, что должно быть 1,62 цифры, так еще и левые цифры (-1) вводятся. Никто не пробовал вводить дробные цифры в десятичную, например? Получились бы прикольные штуки, типа, 7'36, где цифра 7' — это 7,5. Или даже (7 + 1/e).
Кто-нибудь тут может объяснить, как эти "ненатуральные" системы работают?
Duduka
04.06.2016 04:54Целочисленные системы имеют конечное множество модулей от оснований, десятичная(-5..4), троичная(-1..1)… это все остатки по модулям. Остатков-же по дробному основанию — бесконечное множество, в том числе и целые, и отрицательные, и рациональные/иррациональные(от комплексного/матрицы остаток — комплексный/митричный), проблема-же и там, и там — большинство чисел не представимы конечным чистом не нулевых цифр.
По своей сути наша запись — апроксимация(приближение), означающая, что мы описываем число, которое: больше некоторого A, но меньше или равно некоторому B, которые выразимы в наших числах, и на систему счисления должны быт наложены ограничения: минимализм(все числа вызаримы только одним образом, например, если -0 и 0 есть в системе — это дефект), адитивность( все представимые числа можно собрать через сложение, ваша система не удовлетворяет этому условию, сумма двух иррациональных чисел не факт, что даст число в вашей системе), и мультипликативность (все представимые числа должны быть либо «простыми» в этой системе, либо быть суммой произведений, и чем меньше «простых», отличных от 0 и 1, тем лучше[флоаты и даблы этому условию не удовлетворяют, они вносят в алгебру дефекты округления и потери точности]), и конечно должны быть представимы 0 и 1, и както отрицательные числа… все это вместе позволяет представить рациональные числа над множеством представимых чисел. Т.е. Вы можете ввести систему по рациональному основанию, которая даст ту же систему, что и отношение двух целочисленных, т.е. без какого-то профита. Но введение иррациональной системы сложно, или вообще не возможно( из-за невозможности построения замкнутой алгебры с конечным числом чисел ), но если потеря алгебраичности приемлема, то возможно создания и вашей системы.
Starche
Поиграл в вашу игру. Понравилось) Вроде бы нашёл алгоритм, который можно быстренько запрограммировать (правда, лень).
1) Спускаем всё вниз
2) Нормализуем последний ряд
3) Повторяем 1-2 пока не зайдём в тупик
4) Денормализуем самую правую единицу во втором снизу ряду
5) Повторяем 1-2-3-4 пока не завершим.
Sirion
Да, это должно работать на всех (конечных) входных данных.