Рамиль Альварес Х.1, Владимирова Ю.С.2
гМГУ им. М.В.Ломоносова, ф-т ВМК, гатП@ cs . msu. ги 2МГУ им. М.В.Ломоносова, ф-т ВМК, у^ткоуа . msu. ги
ОБ ИЗВЛЕЧЕНИИ КВАДРАТНОГО КОРНЯ В ТРОИЧНОЙ СИММЕТРИЧНОЙ
СИСТЕМЕ
КЛЮЧЕВЫЕ СЛОВА
Троичная симметричная система, извлечение квадратного корня. АННОТАЦИЯ
В статье [1] описаны алгоритмы деления и извлечения квадратного корня типа «цифра за цифрой» в троичной симметричной системе (ТСС). К сожалению, в алгоритме извлечения квадратного корня автором допущена ошибка, которая исправлена при описании алгоритма в [2], в работе [3] приведено описание алгоритма на языке С [4]. Однако эти работы малодоступны, а в интернете [5] приводятся ошибочные алгоритмы деления и извлечения квадратного корня в ТСС. Эти ошибки носят методологический характер и связаны с перенесением с некоторой корректировкой на алгоритмы в ТСС методов и приемов из двоичной или десятичной систем.
Общие правила извлечения квадратного корня
Как и при вычислении квадратного корня в десятичной системе, подкоренное число N разбивается на пары цифр (тритов) влево и вправо от точки. Обозначим через Ni целое число, получаемое из первых слева направо , пар тритов, А, - целое значение квадратного корня из этого числа, D/ - /-ая пара тритов, й, - значение /-го трита корня и п - число пар тритов. Если старшая пара состоит из одного трита, добавим к ней слева трит 0. Отметим, что действия производятся над целыми числами, а точка в результате будет после к-го трита, если в подкоренном числе она стояла после к-ой пары.
Если рассмотреть теперь подкоренное число как число с точкой перед первой парой, имеем число в интервале (.166... : .5), корень из которого будет в интервале (.408... : .707...). В ТСС числа, удовлетворяющие 0 < х < .5 имеют нулевой трит, равный 0, числа удовлетворяющие .5 < х < 1.5 -нулевой трит, равный 1, откуда, нулевой трит корня может быть 0 или 1. Таким образом, в ТСС корень из числа, состоящего из п пар тритов, может состоять из п + 1 тритов. Например, корень из числа из одной пары тритов 11 (4 в десятичной системе) равен 1 1 (2 в десятичной системе), числу из двух тритов (1 в ТСС обозначается -1).
Схему алгоритма извлечения квадратного корня «в столбик» для ТСС можно описать следующими формулами:
А0 = где й0 = 0 или 1, В = -^0, N. = А,2 + В/, С = ВмЗ2 + D,, В, = С - (2АМ3 + А, = Ам3 + й,.
Заметим, что В,-1З2 + Di при ручном использовании алгоритма выполняется приписыванием справа к значению Вм двух тритов пары D,■, а 2А,-13 + й, и А,-1З + й, - трита й, соответственно к числам 2АМ3 и Ам3.
Для вычисления значения квадратного корня приведенную схему необходимо дополнить правилом выбора очередной цифры й,. Определение й0
Если подкоренное число, рассматриваемое как число с точкой перед первой парой, больше .25, корень больше, чем .5, т.е. нулевой трит корня йо будет 1. В противном случае корень меньше, чем .5, и нулевой трит корня йо будет 0. Значение В0 в первом случае равно 1, во втором 0, согласно схеме алгоритма. Заметим, что .25 не представляется точно в ТСС и имеет представление
в виде бесконечной последовательности .(1 1). Обоснование правила выбора di
Для получения правила определения di, i = 1, 2, ... покажем, что при di - z-ой цифре Ai значение |B,| минимально из трех возможных. Рассмотрим функцию дискретной трехзначной переменной b,(x) = Ci - (2-3Am + x)x,
x £ { 1, 0, 1}. Отметим, что b,(di) = Bi, где di - i-ая цифра Ai = [ VN; ]. Утверждение 1. В ТСС значение |b,(x)| = |Ci - (2-3A„1 + x)x|, x £ {-1, 0, 1} достигает минимума при x = di, i = 1, ..., n.
Доказательство. Отметим, что на i-м шаге (i > 1) Ai > 1. В самом деле, при i = 1 старшая пара цифр Dt подкоренного числа по условию больше нуля, т.е. 1 < Dt < 4. В силу того, что N1 = Dt и A1 = [ VN i ], Ai > 1. На следующих шагах, при i = 2, ..., n, Ai = Ам3 + di, откуда Ai > 1. Оценим |Bi|. Из того, что
Ai = [ VN ],
следует:
B, =N, - Ai2 = N, - [ VN ]2. Для того чтобы оценить модуль разности |Ni - [ V]2|, представим V= Ai + z, где z -дробная часть VNt :
Ni = (Ai + z)2 = a,2 + 2A,z + z2,
откуда:
Bi =Ni - A2 = 2A,z + z2 (1)
Так как в ТСС |z| < 0.5,
|B,| < Ai + 0.25. (2)
Отметим также, что поскольку
a,2 = (3AM)2 + (2-3Am + d,)d, ,
то Bi можно представить как:
Bi = Ni - (ЗА/,1)2 - (2-ЗАм + di)di. Докажем, что |B,| = |bi(di)| - минимально.
Предположим обратное: |B,| = |C - 2^(3Ам + di) di | - не минимально, di £ { 1, 0, 1} является i-ой цифрой А,. Тогда существует число t = ±1, ±2, такое что (di + t) £ { 1, 0, 1} и
|bi(di + t)| < |B,|.
Преобразуем:
b(di + t) = Ni - (ЗАм)2 - (2^3Ам + di + t)(di + t) =
= N, - (3AM)2 - ((2^3Ам + d,)d, + (2^3AM + t)t + 2d,t) = = Bi - ((2-ЗАм + t)t + 2d it) = = Bi - 2-(3Ам + di)t - t2 = Bi - (2Ait + t2). Обозначив
R = 2Ait + t2,
получим
bi(di + t) = Bi - R. По предположению, |B,| не минимально, т.е.
bid, + t)| = |Bi - R| < |B/|. (3)
Нетрудно убедиться, что при R > 0 условие |B, - R| < |B,| выполняется, если R < 2B,, а при R < 0, если R > 2B.
При A, > 1, если t > 0, то и R > 0, а если t < 0, то и R < 0. При А, = 1 это верно не при всех значениях t. Рассмотрим в связи с этим раздельно случаи А, > 1 и А, = 1. Рассмотрим случай Ai > 1.
Допустим, что t > 0, тогда и R > 0. Согласно предположению (3), при R > 0 имеет место R < 2B,.
Используя оценку (2), получим
R < 2B, < 2Ai + 0.5. (4)
С другой стороны, т.к. R = 2At + t2, наименьшее значение R > 0 R = 2Ai + 1 > 2Ai + 0.5,
что несовместимо с (4).
Допустим, что t < 0, тогда и R < 0, и согласно предположению (3),
R > 25, (5)
Отсюда следует, что Bi < 0. Отметим также, что при t < 0, т.е. t = -1 или t = -2, /-ая цифра результата di £ {0, 1}.
Из (2) следует оценка для 2B,-:
2B, > -2A, - 0.5.
В силу того, что Bi и Ai - целые числа, полученная оценка сводится к:
2Bi > -2A,. (6)
Выясним, при каких условиях неравенство (5) и (6) совместимы, т.е. возможно
-2Ai < 2Bi < R.
R может принимать одно из двух значений: R = -4A, + 4 (при t = -2) или R = -2А,- + 1 (при t = -1).
При Ai > 1, t = -2 выполнено -4A, + 4 < -2A,-, т.е.
R < -2Ai < 2Bi,
что несовместимо с (5).
При t = -1 значение R = -2A, + 1, откуда (5) выполнено только в случае, если 25,- = -2A,-, т.е. Bi = -a,-. В силу (1)
в, = 2A,z + z2.
В рассматриваемом случае
2A,z + z2 = -A,-,
откуда
Ai = 2-+Г . (7)
2 z + 1
По предположению, A, > 1, откуда число в правой части (7) положительно, если 2z + 1 < 0
или
z<-.5 ,
что невозможно в силу того, что z - дробная часть числа в ТСС, и | z |< .5 . Таким образом, при A/ > 1 и t < 0 невозможно B, = -A,-, и предположение, что R > 2B, неверно.
Рассмотрим случай A/ = 1, i = 1, ..., n. Очевидно, что A, = 1 может быть только при i = 1 и A0 = 0. Тогда dt = 1, и
B1 =C - 2A03dt - d12 = D1 - 1.
Поскольку
bt(x) = C1 - (2-3A0 + x)x = D1 - x2, x £ {-1, 0, 1}, значение D1 - 1 минимально для b1(x). Утверждение 1 доказано. Утверждение 2. Докажем, что
1) |B,| единственный минимум |b,(x)| при A/ > 1 (/ = 2, ..., n) и при A0 = 1 (/ = 1);
2) |b,(x)| может иметь два минимума при A0 = 0 (/ = 1), только один из которых соответствует старшему триту результата, а он положительный.
Доказательство. 1) Предположим, что для некоторой цифры d* d/, d/' £ { 1, 0, 1} соответствующее ей значение
|bi(di')| = IN - (3A/-1)2 - (2^3A,--1 + d,-')di'| также минимально, т.е. |b/(d/')| = |B,|. Рассмотрим функцию вещественной переменной
fix) = | b/(x) | = |N, - (3AM)2 - (2-3A/.1 + x)x|
и исследуем ее на сегменте [-1; 1]. Преобразуем fx):
fx) = |-x2 - 2^3A,--1x + N, - (3Ai-1)2| = |x2 + 2-3AMx - N, + (3AM)2|. Функция fx) имеет два минимума, равных нулю, в точках
xx,2 = -3A/-1 ± VN . В силу того, что на /-ом шаге при i = 2, ..., n, A,-1 > 0 или при i = 1, A0 = 1,
xx = -3A/-1 - VNt < -3 < -1, т.е. точка x1 лежит вне сегмента [-1; 1]. Откуда функция fx) имеет на сегменте [-1, 1] единственный минимум.
2) Рассмотрим случай i = 1, A0 = 0. Функция fx) = |x2 - N1I достигает минимума на концах сегмента [-1; 1]. Значение fx) в точке x2 = 1 соответствует положительному старшему триту
результата di = 1. Утверждение 2 доказано.
Определение di
Согласно доказанным утверждениям, в качестве очередного di выбирается троичная цифра, для которой |b,(x)| = IC, - 2^(3Am + x)x| минимально, т.е. минимальное из трех значений:
|b,(-1)| = |C, + (2-3A-1 - 1)|, (8)
Ь(0)| = |C|, (9)
|b,(1)| = |C, - (2^3A,-i + 1)|. (10)
Знак в выражениях под модулем в (8) и (10) зависит от того AM > 1 или Ai-1 = 0, поэтому рассмотрим эти случаи раздельно.
Отметим, что при C, > 0 в случае Ai-1 > 1, (i = 1, 2, ..., n).
|C + (2-3A¿-1 - 1)| > C, |C, + (2-3Am - 1)| > |Ci - (2^3A i-1 + 1)|, т.е. (8) не может быть минимальным, и d, t 1 .
Аналогично, при C, < 0:
|C - (2-3 Am + 1)| > |C|, |C - (2^3A i-1 + 1)| > |Ci + (2-3Ai-1 - 1)|, т.е. (10) не может быть минимальным, d, t 1. Таким образом, если d, отлично от 0, его знак совпадает со знаком Ci.
При Ci > 0 для определения di необходимо сравнивать (9) и (10). Раскрывая модули в этих выражениях, получим, что если Ci < 3AM, то минимально (9), т.е. di = 0, а если Ci > 3AM, то минимально (10), т.е. di = 1.
Аналогично, при Ci < 0 для определения di необходимо сравнивать (8) и (9), в результате чего получаем, что если Ci < -3AM, то минимально (9), и di = 0, а при Ci > - 3Am то минимально (8), и d, = 1 .
Рассмотрим случай i = 1, A0 = 0. При этом
|Ьх(0)| = |C1|, |Й1(-1)| =|М1)| =|C1 - 1|.
Согласно схеме алгоритма,
C1 = B032 + D1,
где B()= -d0 = -A0 = 0, D1 - старшая пара подкоренного числа, для которой верно 1 < D1 < 4. Таким образом, C1 = D1, 1 < C1 < 4 и
|C1| < |C1 - 1|,
откуда di = 1.
Обобщая, получим следующий критерий выбора очередного di: di = 0 при |C,| < 3Ai-1, и di = sign(C¡) при |Ci| > 3Ai-1.
Рассмотрим случай |C,| = 3AM, тогда B, можно представить в виде:
в, = C, - 2AM3d + (.5)2 - .25,
где d = .5 для Ci > 0 и -.5 для Ci < 0. Значение di зависит от значения ni - необработанной части числа N, рассматриваемой как число с точкой перед ее первым тритом. То, что функция квадратного корня возрастающая, позволяет определить значение di. При Ci > 0 и ni >.25 невычисленная часть корня больше .5, т.е. d, будет 1. При C, < 0 и n, <.25 невычисленная часть корня меньше -.5, т.е. d, будет 1.
Описание алгоритма
Целое троичное число представляется в виде структуры
struct trin {int n; char trit [X]}; где n - число тритов, а массив trit - значение числа: младший трит хранится в элементе с индексом 0, элементы массива принимают значения -1, 0 и 1. Для числа нуль n равно нулю. Параметр алгоритма К - максимальная длина числа.
Вспомогательные функции
В виду простоты реализации функций sgn(w), red(&res), shftb(&bi,x,í) и shiftc(&y) их определение на языке C не приводится, даются только словесные описания.
Результатом функции int sgn(struct trín w) является знак числа w. Если n равно нулю, то результат будет нуль, в противном случае, в соответствии со свойством ТСС и принятым представлением числа, результатом будет значение элемента массива trít с индексом n-1.
Функция void red(struct trín *res) приводит число res к принятому представлению, т.е. удаляет старшие нулевые триты структуры res. Она используется в функциях shftb(&bí,x,í) и sum3(x, y, &res).
Функция void shftb (struct trin *bi, struct trin x, int i) определяет новое значение bi. Ненулевое значение bi сдвигается влево на два трита. Тритам с индексами один и нуль присваиваются значения тритов структуры x с индексами, соответственно, i и /-1, после чего производится приведение числа к принятому представлению, т.е. обращение к функции redQ.
Функция void shiftc(struct trin *у) сдвигает влево на один трит значение структуры y и обнуляет трит с индексом нуль.
Функция acmp(x, &у) сравнивает модуль x и y (у > 0). Если длина x больше длины у, результат будет 1, а если длина x меньше длины у, результат будет -1. При равных длинах x и у сравниваются триты чисел x и у с учетом знака x, начиная со старших, до первого несовпадения, которое определяет результат. Если все триты совпали, то результат - нуль.
int acmp(struct trin x, struct trin * у) { int i = x.n, sx = sgn(x);
if (i >у->п) return 1; if (i-- ==у->п) { while (sx * x.trit[i] == y->trit[i] && i-- >= 0); if (i<0) return 0;
if (sx * x.trit[i] > у-^пф']) return 1;
}
return -1;
}
Функция cmp(x, k) производит сравнение необработанной части структуры x с индексами с k по нуль (рассматриваемой как число с точкой перед k-ым тритом) с числом .25. Поэтому сравниваются последовательно пары тритов структуры x и пара 1 1 .
int cmp(struct trin x, int k)
{
int i = k;
while ((i > 0) && (x.trit[i] == 1) && (x.trit[i - 1] == -1)) i -= 2;
if ((i > 0) && (x.triti == 1) && (x.trit[i - 1] > -1)) return 1;
else return -1;
}
Функция sum3(x, у, &res) производит вычисление по формуле res = x - 1 - (у + y)sign(x). Практически это одновременное сложение трех слагаемых, заметим, что в этом случае, также как и при обычном сложении, перенос возможен только одной единицы (положительной или отрицательной). Максимальное значение суммы тритов будет при совпадении знаков суммируемых тритов и трита переноса и равно ±4, и это дает перенос в следующий трит единицы того же знака (1 или -1). Отметим, что при обычном сложении трех слагаемых начальное значение этого трита (переменная c1) равно нулю, в данном случае в связи с формулой вычисления res начальное значение трита равно -1.
Заметим, что трехвходовые сумматоры использовались в ЭВМ «Сетунь» [6] в множительном устройстве. Для умножения 18-тритных чисел на первом уровне использовалось 6 трехвходовых сумматоров, на втором - 2 трехвходовых сумматора для суммирования результатов первого уровня, а на третьем уровне - один обычный (двухвходовый) сумматор для суммирования результатов второго уровня. Это позволило для последовательности выполнения операций выполнять умножения за 320 машинных тактов, притом, что сложение выполнялось за 180 тактов.
void sum3 (struct trin x, struct trin * у, struct trin * res)
{
int i; s; sx = sgn(x); c1 = -1; j = max(x.n;у-> n);
res-> n = j ;
for (i = 0; i < j; i ++)
{
s = c1;
if (i < x.n) { s += x.trit[i]; } if (i <у-> n) { s -= (у-> trit[i] + у-> trit[i]) * sx; } if (s < -1) { res-> trit[i] = s + 3; c1 = -1; } else
if (s > 1) { res-> trit[i] = s - 3; c1 = 1; } else { res-> trit[i] = s; c1 = 0; }
}
if (c1 != 0) { res-> trit[j] = c1; res-> n = j + 1; } else red(res);
}
Алгоритм извлечения квадратного корня
Функция sqrt(x, &y) производит вычисление квадратного корня числа x. void sqrt (struct trin x, struct trin *y) int i = x.n; j, sbi, k, cmpbc; struct trin bi, cx = x; if (i == 0) y->n = 0; else {
if (x.trit[z - 1] < 0) printf ("Number less 0\n"); else {
if ((i&1) == 1) { // первая пара состоит из одного трита
cx.n++; cx.trit[i] = 0; }
}
}
j = cx.n >> 1; // j - индекс старшего трита корня if (cmp(cx, j + j - 1) == 1) // cx больше .25
{bi.n = 1; bz.trit[0] = -1; y-> n = 1; y-> trit[0] = 1;} // bi=-1, ai=1 else { bi.n = 0;y-> n = 0; } // bi=0 и ai=0 for (/--; j >= 0; j--)
{ // определение j-го трита корня shiftb(&bi, x, i); shiftc(y); sbi = sgn(bi); cmpba = acmp(bi,y);
if ((cmpba == 1) II (cmpba == 0) && (cmp1(cx, j + j - 1) == sbi)) { // j -й трит корня не нуль sum3(bi,y, &bi); if (y-> n == 0) {y->n = 1; } y-> trit[0] = sbi; } // if } // for } // else
} // конец функции
Литература
1. Рамиль Альварес Х. Алгоритмы деления и извлечения квадратного корня в троичной симметричной системе // Вестн. Моск. Ун-та. Серия 15. Вычислительная математика и кибернетика. № 2, 2008. С. 42-45.
2. Рамиль Альварес Х. Троичный алгоритм извлечения квадратного корня / / Программные системы и инструменты. №. 11. - М.: МАКС Пресс, Москва, 2010. С. 98-106.
3. Рамиль Альварес Х. Извлечение квадратного корня в троичной симметричной системе // Рамиль Альварес Х. Алгоритмы троичной арифметики. М: Фонд «Новое тысячелетие», 2012. С. 14-19.
4. Березин Б.И., Березин С.Б. Начальный курс C и C++. М: ДИАЛОГ МИФИ, 2005.
5. Balanced ternary [Электронный ресурс] Электрон. дан. - URL: https://en.wikipedia.org/wiki/Balanced_ternary (дата обращения 12.10.2015)
6. Брусенцов Н.П., Маслов С.П. и др. Малая цифровая вычислительная машина «Сетунь». М.: Изд-во МГУ 1965.