Как конфертировать из неуравновешенного в сбалансированное троичное?
Моя цель - преобразовать десятичное число в сбалансированное троичное. Преобразование из десятичного в несбалансированное троичное просто требует деления на 3 и отслеживания остатков. Как только я получу несбалансированное троичное представление числа, я не могу понять, как его "сбалансировать".
Например: 15 в десятичном виде это 120 в несбалансированной троичной и +- 0 в сбалансированной троичной. Как мне перейти от 120 до +-0? Я не могу понять, как бороться с двумя в несбалансированном троичном представлении.
Спасибо!
2 ответа
Обратите внимание, что 2 в троичной системе - это +- в сбалансированной троичной форме или в десятичной системе счисления 2 = 3 - 1. Так что, если вы начинаете с массива, заполненного 0, 1 и 2, просто замените каждые 2 на -1 и добавьте 1 к номер слева. (Убедитесь, что у вас есть дополнительный 0 в начале числа, по крайней мере, если он начинается с 2.) В зависимости от того, как вы выполняете замену, вам также может понадобиться заменить 3 на 0, добавив 1 как обычно слева. Затем повторяйте процесс до тех пор, пока не останется 2 с (или 3 с).
Один из способов увидеть это, если вы получаете остаток 2
с оставшимся частным x
, это эквивалентно получению остатка -1
с оставшимся частным x+1
,
Преобразование тогда подобно простому преобразованию в троичное основание с одной дополнительной проверкой.
String output="";
while (n>0) {
rem = n%3;
n = n/3;
if (rem == 2) {
rem = -1;
n++;
}
output = (rem==0?'0':(rem==1)?'+':'-') + output;
}
Работающую программу можно найти здесь.
Смещенная троичная система против сбалансированной тройной
"Тернарный манифест " Дугласа У. Джонса - отличный источник информации по теме (сбалансированного) троичного представления. Автор отмечает, что
сбалансированное троичное кодирование в точности эквивалентно смещенному кодированию
Смещенное кодирование - это способ кодирования чисел со знаком в (ограниченных) числах без знака с использованием смещения b. Чтобы прочитать смещенное число, прочтите его как обычно, затем вычтите b, чтобы получить представленное значение.
Дуглас В. Джонс описывает связь между троичными смещенными и сбалансированными числами следующим образом, приводя пример с двумя троичными цифрами (= триц).
Decimal Biased Balanced 4 22 ++ 3 21 +0 2 20 +- 1 12 0+ 0 11 00 -1 10 0- -2 02 -+ -3 01 -0 -4 00 --
[...]
естественное смещение b для n-тройного троичного числа - все единицы:
b = ⌊3n / 2⌋ = (3n-1) / 2
[...]
Чтобы преобразовать смещенные числа в сбалансированные числа, вычтите 1 из каждой цифры, так что 2 станет+1
(представлен как+
), 1 становится0
(представлен как0
), а 0 становится–1
(представлен как-
).
[...]
Это просто изменение символов, связанных с цифрами, вопрос того, как цифры напечатаны на странице, а не вопрос того, как цифры представлены внутри некоторого механизма. Разницу между предвзятым и сбалансированным представлениями можно считать чисто косметической.
Преобразование целых чисел в сбалансированный троичный
Чтобы преобразовать целое число i в сбалансированное троичное
- Вычислите n, количество цифр в сбалансированном троичном представлении i.
Решая | i | ≤ (3n-1) / 2 для n, мы знаем, что n = ⌈log3(2 | x | +1) ⌉. - Вычислите смещение b = (3n-1) / 2.
- Затем преобразуйте i+b в троичную строку с n цифрами (ведущие
0
важны!), - и замените символы
012
по-0+
.
Пример реализации в Java jshell:
import static java.lang.Math.*;
String balTer(int i) {
// n=…+1 and ….substring(1) ensure leading zeroes
int n = max(1, (int) ceil(log(2 * abs(i) + 1) / log(3))) + 1;
int b = ((int) pow(3, n) - 1) / 2;
return Integer.toString(i + b, 3).substring(1)
.replace('0', '-').replace('1', '0').replace('2', '+');
}
balTer(15) // returns "+--0"
Поскольку мне не хватало этого в Интернете, вот моя собственная реализация в Pari/GP -
{balanced_ternary(x,maxdigits=20,chars=["y","0","1"])=my(res,st,dez,dig);
dez=floor(log(abs(2*x))/log(3));
res=x/3^dez;
st="";
for(k=0,maxdigits,
if(k==dez+1,st=Str(st,"."));
dig = if(res>1/2
,res--;chars[2+1]
,if(res<-1/2
,res++;chars[2-1]
,chars[2+0]
));
st=Str(st,dig);res*=3
);
return(st);}
потом
balancedternary (1) \\ %1002 = "1.00000000000000000000"
balancedternary (-1) \\ %1003 = "y.00000000000000000000"
balancedternary (1.2) \\ %1004 = "1.1yy11yy11yy11yy11yy1"
balancedternary (-1.2) \\ %1005 = "y.y11yy11yy11yy11yy11y"
balancedternary (27-3) \\ %1006 = "10y0.00000000000000000"
balancedternary (400) \\ %1007 = "1yy0y11.00000000000000"
balancedternary (sqrt(3)) \\ %1008 = "1y.y1yy10y0000yy1100y0"
balancedternary (sqrt(3)/3) \\ %1009 = "1.yy1yy10y0000yy1100y0"
Просто q&d, не все "особые случаи" проверены / закодированы.
Я знаю, что этот вопрос касается преобразования из обычного троичного, но FWIW, вы также можете достичь поставленной цели, перейдя прямо от десятичного к сбалансированному тройному, например, с помощью программ на