Помощь - Поиск - Пользователи - Календарь
Полная версия: операции над сист счисления
Форум «Всё о Паскале» > Разработка ПО, алгоритмы, общие вопросы > Алгоритмы
AlexSt
mega_chok.gif good.gif yes2.gif mega_chok.gif есть отличный программный код для умножения и сложения двух чисел в разл системах(целых через строковый тип) помогите реализовать такие же функции для вычитания и деления(это самое главное!))), ещё желательно чтобы все функции решали задачи и для вещественных чисел, сдавать через неделю( unsure.gif unsure.gif unsure.gif вот код:
Code:

// Модуль для работы с натуральными числами в различных системах исчисления

// Далее, если говорится, что Система Исчисления (СИ) задается строкой (CharSet)

// то имеется в виду, что эта строка содержит символы требуемой СИ, начиная с нуля

// Примеры CharSet (стандартный вид)

// Двоичная - '01'

// Восьмиричная - '01234567'

// Десятичная - '0123456789'

// Шестнадцатиричная - '0123456789ABCDEF'

// Можно использовать и нестандартные виды, например для двоичной 'ab', а для

// троичной 'abc' - данному модулю все равно.



// "-Ричность" СИ ограничена только наличием доступных различных символов.

// Работа с числами в определенной СИ производится как со строками, потому величина

// чисел значения почти не имеет, но это отрицательно сказывается на времени работы

// функций (особенно на умножении).

unit MyUnit;



interface



function Convert(Num, SetIn, SetOut: String): String;

function MySum (Num1, Num2, CharSet: String): String;

function MyMulti (Num1, Num2, CharSet: String): String;

function MyOrd(A: Char; CharSet: String): Integer;

function MyChr(Num: Integer; CharSet: String): Char;



implementation



// Функция возвращает позицию символа A в строке CharSet (начиная с 0)

function MyOrd(A: Char; CharSet: String): Integer;

var

i: Integer;

begin

Result := 0;

for i := 1 to Length(CharSet) do

begin

if CharSet[i] = A then begin

Result := i-1;

exit;

end

end;

end;



// Функция возвращает символ из строки CharSet по номеру Num (~CharSet[Num+1])

function MyChr(Num: Integer; CharSet: String): Char;

begin
Result := CharSet[Num mod Length(CharSet) + 1];
end;

// Функция возвращает число без ведущих нулей, то есть ShortNum('0000123')='123'
function ShortNum(Num, CharSet: String): String;
var
k, j: Integer;
begin
Result := '';
k := 1;
while Num[k] = MyChr(0, CharSet) do
k := k + 1;
for j := k to Length(Num) do Result := Result + Num[j];
end;

// Функция выполняет сложение двух чисел Num1 и Num2 в СИ, задаваемой CharSet
function MySum (Num1, Num2, CharSet: String): String;
var
i, Pos, Add, L, L_CharSet: Integer;
N1 , N2 , O, Res: String;
begin
// Далее потребуется что бы первое число по длине было не менее второго,
// если не так, то меняем местами
if Length(Num1)>=Length(Num2) then
begin
N1 := Num1;
N2 := Num2;
end
else
begin
N1 := Num2;
N2 := Num1;
end;
L:= Length(N1);
L_CharSet := Length(CharSet);
O:=MyChr(0, CharSet); // 0 - в СИ, определяемой CharSet
//Уравнняем второе до длины первого нулями справа: 10 = 010
for i := Length(N2) to L-1 do
N2 := O + N2;
Add:=0;
//Суммирование с младших разрядов, Add - добавка от предыдущих разрядов
// для следующего. Напр. для 10-чной СИ: 9+7 - Add = 1, 4+5 - Add=0
for i := L downto 1 do
begin
Pos := MyOrd(N1[i], CharSet)+MyOrd(N2[i], CharSet) + Add;
Add := 0;
while Pos >= L_CharSet do
begin
Pos := Pos mod L_CharSet;
Add := Add + 1;
end;
Res := MyChr(Pos, CharSet) + Res;
end;
If Add<>0
then Result := MyChr(Add, CharSet) + Res
else Result := Res;
end;
// Функция выполняет умножение двух чисел Num1 и Num2 в СИ, задаваемой CharSet
function MyMulti (Num1, Num2, CharSet: String): String;
var
i, e, Res, N1, N2: String;
begin
N1 := ShortNum(Num1, CharSet);
N2 := ShortNum(Num2, CharSet);
i :='';
Res := '';
//e - единица СИ, определяемая CharSet
e := MyChr(1,CharSet);
//Умножение Num1 на Num2 - это Num1 сложеное Num2 раз в СИ, определяемой CharSet
while (i <> N2) do
begin
Res := MySum(Res, N1, CharSet);
i := MySum(i, e, CharSet);
end;
Result := Res;
end;

// Функция выполняет преобразование одноразрядного числа A, заданного
// в СИ, определяемой SetIn, в число в СИ, определяемой SetOut

function f0(A: Char; SetIn, SetOut: String): String;

var
Pos, j, L: Integer;
Res: String;
begin
L := Length(SetOut);
Pos := MyOrd(A, SetIn);
for j := 1 To Pos div (L-1) do
Res := MySum(Res, MyChr(L-1, SetOut), SetOut);
Result := MySum(Res, MyChr(Pos mod (L-1), SetOut), SetOut);
end;
// Функция выполняет преобразование числа Num, заданного
// в СИ, определяемой SetIn, в число в СИ, определяемой SetOut
function Convert(Num, SetIn, SetOut: String): String;
var
Base, Multiplier, N, Res: String;
i: Integer;
begin
// Num = MultilplierN * Base^N + ... + Multiplier0 * Base^0
// Base - основание СИ, это всегда <последний символ CharSet>+<нулевой символ> ~ 10
// MultiplierI - множитель при соответствующей степени
// Напр. для 10-чной СИ - 123 = 1 * 10^2 + 2 * 10^1 + 3 * 10^0
// Тут Base = 10, Multiplier = {1, 2, 3}
Base := MySum(f0(MyChr(Length(SetIn)-1, SetIn), SetIn, SetOut), MyChr(1, SetOut), SetOut);
N := MyChr(1, SetOut); // = Base^0, потом будем домножать на Base (в соотв. СИ)
Res := '';

// Обрабатываем входящее число с хвоста
for i := Length(Num) downto 1 do
begin
Multiplier := f0(Num[i], SetIn, SetOut);
Res := MySum(Res, MyMulti(Multiplier, N, SetOut), SetOut);
N := MyMulti(Base, N, SetOut);
end;
Result := Res;
end;
end.

Lapp
AlexSt, пожалуйста, не дублируй темы.

 ! 
Два дубля этой темы удалены.


AlexSt
помогите модернизировать алгоритм конвертации чисел(чтобы конвертировал числа с дробной частью), или на словах хотя бы напишите что делать. give_rose.gif
function Convert(Num, SetIn, SetOut: String): String;
var
Base, Multiplier, N, Res: String;
i: Integer;
begin
// Num = MultilplierN * Base^N + ... + Multiplier0 * Base^0
// Base - основание СИ, это всегда <последний символ CharSet>+<нулевой символ> ~ 10
// MultiplierI - множитель при соответствующей степени
// Напр. для 10-чной СИ - 123 = 1 * 10^2 + 2 * 10^1 + 3 * 10^0
// Тут Base = 10, Multiplier = {1, 2, 3}
Base := MySum(f0(MyChr(Length(SetIn)-1, SetIn), SetIn, SetOut), MyChr(1, SetOut), SetOut);
N := MyChr(1, SetOut); // = Base^0, потом будем домножать на Base (в соотв. СИ)
Res := '';

// Обрабатываем входящее число с хвоста
for i := Length(Num) downto 1 do
begin
Multiplier := f0(Num[i], SetIn, SetOut);
Res := MySum(Res, MyMulti(Multiplier, N, SetOut), SetOut);
N := MyMulti(Base, N, SetOut);
end;
Result := Res;
end;
end.
AlexSt
что, никто не может объяснить даже на словах как замутить с дробной частью???java script:emoticon(':blink:', 'smid_2')
Lapp
Послушай, AlexSt, а сам-то ты что-нибудь сделал?..
Насколько я понял, ты притащил чужой код и просишь нас изменить его для тебя. А кому от этого какая польза? Только та, что ты зачет сдашь?

Твоя задача, на самом деле, интересная и не очень простая. Но копаться в чужом коде лично я не хочу. Лично мне удобнее и быстрее было бы написать свою прогу. И тебе я рекомендую сделать именно это. С нуля. И если ты решишься на это - помощь я тебе гарантирую (как минимум - свою). А так - какой смысл? Ты правда думаешь, что мне так хочется, чтоб ты сдал свой зачет или что там у тебя?.. Вот научить тебя я хочу. Честно.

Кстати, добавление возможности вещественных чисел к этой программе - совсем не такая простая вещь. Например, для конвертации тебе понадобится деление. Если ты все же хочешь переделывать эту программу, разберись, как она работает. Я готов отвечать на твои вопросы (по делу).
AlexSt
в проге я разобрался, сам сделал вычитание, хочу ща сделать конвертацию без деления... будут вопросы - отпишусь
Lapp
Цитата(AlexSt @ 15.12.2007 11:19) *

в проге я разобрался, сам сделал вычитание, хочу ща сделать конвертацию без деления...
Вот это мне нравится smile.gif.
Буду следить за темой.


Добавлено через 18 мин.
Некоторые соображения общего характера.. Из истории арифметики smile.gif.

Как появились числа? Просто люди стали считать - пальцы, коров..
Какие это были числа? Натуральные (то есть 1, 2, 3...)
Потом появилось сложение.
Многократное сложение - это умножение.
Сначала система счисления была римская - в ней считать неудобно.
Потом появилась десятичная запись. Что она собой представляет? Сумму произведений цифр на основание системы.

Теперь остановимся и посмотрим на ту прогу, которую ты привел. Что там есть? Мне видится, что главное там - конвертация. Для нее нужно уметь умножать (цифры на основание). Для умножения надо уметь складывать. Чувствуешь аналогию с историческим процессом? smile.gif

Идем дальше.
Появилось вычитание - как действие, обратное сложению.
Вычитание повлекло расширение натуральных чисел, добавление к ним нуля и отрицательных чисел.
Что такое число "-5"? Это результат операции "0-5". То есть отрицательные числа просто заменили длинную запись (операцию) на короткую (отрицательное число).
(попутно вопрос: ты ввел отрицательные числа, когда сделал вычитание? без этого нельзя)

Наконец, появилось действие, обратное умножению - деление.
Оно также повлекло за собой расширение понятия числа - появились дробные числа.
Что такое 1/5? Это результат операции 1:5 - то есть снова просто укороченная запись, а по сути одно и то же.
Как видишь, дробные числа не бывают без деления smile.gif.

Но я буду рад, если ты мне докажешь обратное smile.gif
AlexSt
ок, только что весьма надёжно получилось сделать умножение с дробной частью, думаю сам смогу сделать и вычитание, для деления хочу перевести числа в десятичную разделить и перевести обратно в нужную сс. остаётся только конвертация чисел с дробной частью... я бы хотел узнать как вообще должна вести себя запятая при конвертации в другую сс?
AlexSt
и ещё там есть ф-ция преконверт, гре я пытался сделать перевод в др. сс с запятой, но нажимая выполнить прога виснет( почему?
AlexSt
и ещё, под каким номером находится shift и space, в книге не могу найти(, знаю enter - #13, backspace - #8...
andriano
Пробел - #20, у Shift кода нет - это клавиша-модификатор. Если в DOS, то можно определить ее нажатие, анализируя область данных BIOS по смещению $17 и $18.
AlexSt
спасибо за подсказочку 4.gif , сегодня за целый день наваял код по конвертированию в др сс с дробной частью, но он работает некорректно, может кто сможет найти ошибку? - ф-ция преконверт (у неё в подопечных ф-ция конверт для перевода целой части) ypriamii.gif ypriamii.gif bomb.gif pardon.gif

function preConvert (Num1, SetIn, SetOut: String): String;
var

Res, Resmod, Numdiv, Nummod, mod1, NumSt: String;
m: char;
i, j, Numi, lNumi, k: Integer;
b:boolean;

begin
m:=' ';
b:=true;
Resmod := '';
Res:='';
if num1[1]='-' then
begin m:='-';
delete(num1,1,1);
end;
for i:=1 to length(num1) do
begin if num1[i]=',' then
begin if b=true then
begin Numdiv := copy(num1, 1, i-1);
Nummod := copy(num1, i+1, length(num1));
Nummod := convert(nummod, setin, set10);
Numdiv := convert(numdiv, setin, setout);
Numi := StrToInt(Nummod);
lNumi := Length(Nummod);

// Конвертируем дробную часть в новой системе исчисления
// с точную 6 знаков после запятой
for j := 1 to 6 do
begin Numi := numi*Length(setOut); // Дробную часть числа будем домножать на номер SetOut
NumSt := IntToStr(Numi);
k := Length(NumSt)-lNumi;
if k > 1 then
begin mod1 := copy(NumSt, 1, k-1);
delete(NumSt, 1, k-1);
Resmod := MySum(Resmod, mod1, SetOut);
end;
numi := StrToInt(NumSt);
if k > 0 then Resmod := Resmod + copy(NumSt, 1, 1);
delete(NumSt, 1, 1);
if k = 0 then Resmod := Resmod + '0';
end;
if length(Resmod) > lNumi then
begin Res:= MySum(Numdiv, copy(Resmod, 1, length(Resmod) - lNumi), SetOut);
delete(Resmod, 1, length(Resmod) - lNumi);
end
else Res := Numdiv;
Resmod := ',' + Resmod;
b:=false;
Res:=Res + Resmod;
end
end

end;
if Res='' then Res:=convert(num1, setin, setout);
Result := m + Res;
end;


// Функция выполняет преобразование числа Num, заданного
// в СИ, определяемой SetIn, в число в СИ, определяемой SetOut
//////////////////////////////////////////////////////
function Convert(Num1, SetIn, SetOut: String): String;

var

Base, Multiplier, N, Res : String;
i: Integer;

begin

// Num = MultilplierN * Base^N + ... + Multiplier0 * Base^0
// Base - основание СИ, это всегда <последний символ набора>+<нулевой символ> ~ 10
// MultiplierI - множитель при соответствующей степени
// Напр. для 10-чной СИ - 123 = 1 * 10^2 + 2 * 10^1 + 3 * 10^0
// Тут Base = 10, Multiplier = {1, 2, 3}

Base := MySum(f0(MyChr(Length(SetIn)-1, SetIn), SetIn, SetOut), MyChr(1, SetOut), SetOut);

N := MyChr(1, SetOut); // = Base^0, потом будем домножать на Base (в соотв. СИ)

Res := '';

// Обрабатываем входящее число с хвоста

for i := Length(Num1) downto 1 do

begin Multiplier := f0(Num1[i], SetIn, SetOut);

Res := MySum(Res, MyProiz(Multiplier, N, SetOut), SetOut);

N := MyProiz(Base, N, SetOut);

end;

Result := Res;

end;
Lapp
Цитата(AlexSt @ 16.12.2007 21:26) *
наваял код по конвертированию в др сс с дробной частью, но он работает некорректно, может кто сможет найти ошибку? - ф-ция преконверт (у неё в подопечных ф-ция конверт для перевода целой части)
Видимо, не в подопечных, а в подручных.. smile.gif

Посмотрел я твой код.. Если честно - до конца не разобрался, но у меня есть подозрение, что это не нужно.

Хотя тут сайт про Паскаль, по-русски иногда говорить тоже желательно smile.gif. Пожалуйста, опиши свою идею по переводу словами. Тогда разбирать твою прогу будет намного проще.
Заранее скажу, что если она (основная идея) состоит в том, чтобы разделить число на целую и дробную части, перевести их по отдельности в другую СС (систему счисления, так правильно, не "исчисления"), а потом снова слепить вместе через десятичную точку (а мне показалось, что ты хочешь делать именно так), то вынужден тебя разочаровать - этот путь неверный. Он неверен в корне, а не в отдельных деталях, так что, я думаю, его и подправить нельзя sad.gif. Именно поэтому я прекратил разбор твоего кода, когда заподозрил это.

Пожалуйста, прежде чем предлагать код для выискивания ошибок, говори хотя бы в нескольких словах алгоритм. Ладно?
Если хочешь, можем начать обсуждение работоспособного алгоритма.
AlexSt
а какие ещё есть варианты кроме как "разделить" и "слепить"? у меня только такая идея и была...(
Lapp
Цитата(AlexSt @ 18.12.2007 21:25) *

а какие ещё есть варианты кроме как "разделить" и "слепить"? у меня только такая идея и была...(

Еще вариант - про который я говорил с самого начала.
В той проге, которую ты выбрал за образец, перевод делается так:
Число (А) в записанное в СС1 с основанием D1 нужно перевести в СС2 с основанием D2. Допустим, что мы уже умеем умножать числа в любой системе счисления (одинаковой, естественно, для обоих сомножителей). Переводим каждую цифру этого числа из СС1 в СС2. Теперь это уже, возможно, не цифры, а числа (например, 5 десятичное = 101 двоичное). Дальше действуем по формуле, которую я сегодня уже кому-то тут писал.. Например, исходное число a3a2a1a0 (каждое ai - цифра), то есть:
A(СС1) = a3*D1^3 + a2*D1^2 + a1*D1 + a0

Мы перевели каждую цифру в другую систему ai(CC1) = ai(CC2) = ai2.
Также, мы переводим основание первой системы В1 в СС2

D1(CC1) = D1(CC2) = D12

Теперь перепишем, чему равно А, но уже в СС2:
A(СС2) = a32*D12^3 + a22*D12^2 + a12*D12 + a0

Осталось произвести эти умножения и сложения (теперь понял, почему они есть в той проге?)
Идем дальше, хотим дроби. То есть теперь у нас число выглядит так:
A = a3a2a1a0.b1b2
- тут две цифры после запятой. Переводить его надо аналогично, только с дробными цифрами будут стоять отрицательные степени основания:
A(СС2) = a32*D12^3 + a22*D12^2 + a12*D12 + a0 + b12*D12^-1 + b22*D12^-2

Вот и все. Казалось бы, то же самое. Но только отрицательные степени - это деление:
D12^-n = 1/(D12^n)

То есть, вот так:
A(СС2) = a32*D12^3 + a22*D12^2 + a12*D12 + a0 + b12/D12^1 + b22/D12^2

Так что тебе понадобится деление.
Я бы на твоем месте все сделал заново, без той проги.. Ничего особо сложного, а путаницы меньше. Время есть?



Гость
спасибо, наверно так и сделаю, деление только как...
Lapp
Цитата(Гость @ 19.12.2007 11:16) *

спасибо, наверно так и сделаю, деление только как...

Можно просто обычным уголком smile.gif.
Деление a/b это есть нахождение корня уравнения a=b*x. В оригинале это делается подбором. Способ деления уголком - это и есть подбор (вспомни, каждую цифру приходится подбирать).

Вообще, если хочешь подойти серьезно, рекомендую почитать Кнута.

Я помогу с делением. Только чуть позже.. спать пора smile.gif
AlexSt
Цитата
обычным уголком
))) если есть алгоритм или знаешь где есть отпишись как проснёшся yes2.gif
по поводу времени - его уже нет, курсовую лучше всего было бы сдать завтра (к отчёту ещё и не приступал) mega_chok.gif mega_chok.gif mega_chok.gif
Кнута почитать не успею no1.gif
AlexSt
кстати, к свелению у меня прога на делфы...
я думаю целесообразно буит изменить ф-цию конверт используя "правило уголка"... жду, жду, жду.... give_rose.gif
Lapp
Цитата(AlexSt @ 19.12.2007 19:44) *
к свелению у меня прога на делфы...
Не знаю, к какому "свелению", но это касается интерфейса, о котором пока разговора не было.

Цитата(AlexSt @ 19.12.2007 19:44) *
я думаю целесообразно буит изменить ф-цию конверт используя "правило уголка"... жду, жду, жду....
Ну думаешь - ну делай!
Ты когда нибудь пробовал сделать стол из кровати? Или, скажем, штаны на рубашку перешить?.. Попробуй.

Сделать с нуля, повторяю, проще. Если, конечно, без очковтирательства - типа: авось пронесет - похоже же!
Для вещественного числа нужен соответствующий формат. Если не продумать заранее - получится себе дороже.
Вот, как я бы стал делать, например:
type
tNum= record
m: array[1..L]of integer; {мантисcа}
e,b: integer; {порядок (exp) и основание СС (base)}
n: boolean; {признак отрицательности, минус (negative)}
end;

{нормализация - выравнивание по старшим разрядам, s - отступ слева}
procedure Norm(var a:tNum; s:integer);
var
i,j,k:integer;
begin
k:=0;
with a do begin
while (k<L)and(m[L-k]=0) do Inc(k);
if k=L then e:=0
else begin
Dec(k,s);
if k>0 then for i:=L-s downto 1 do begin
j:=i-k;
if j>0 then m[i]:=m[j] else m[i]:=0
end
else if k<0 then for i:=1 to L do begin
j:=i-k;
if j<=L then m[i]:=m[j] else m[i]:=0
end;
Dec(e,k)
end
end
end;

{сложение чисел в одинаковой СС без учета знаков}
procedure Ad(a,b:tNum; var c:tNum);
var
i,d:integer;
begin
Norm(a,1);
Norm(b,1);
if a.m[L-1]=0 then c:=b
else if b.m[L-1]=0 then c:=a
else begin
if a.e>b.e then Norm(b,a.e-b.e+1) else Norm(a,b.e-a.e+1);
d:=0;
for i:=1 to L-1 do begin
d:=a.m[i]+b.m[i]+d;
c.m[i]:=d mod a.b;
d:=d div a.b
end;
c.e:=a.e;
c.b:=a.b
end
end;

Посмотри. Здесь, конечно, не без недочетов - на скорую руку сляпал.
Если понравится - давай дальше двигать. Вместе.
AlexSt
ого!, здо'рово! попытаюсь разобраться, вот хотел ещё узнать при конвертации если количество знаков в дробной части увеличивается часть из них может перейти в целую часть числа? зависит ли положение запятой от того в большую сс переводишь число или в меньшую? я кстати сделал уголок, но вот запятая всё косячит norespect.gif
не знаю пока, если пойму возьмусь за твою идею)
Lapp
Цитата(AlexSt @ 21.12.2007 12:32) *

хотел ещё узнать при конвертации если количество знаков в дробной части увеличивается часть из них может перейти в целую часть числа?

Дробная часть меньше единицы, целая - больше. Они живут отдельно, независимо. Нет, знаки не могут "переходить".

Я тут на досуге накорябал все четыре действия над вещественными числами smile.gif. Любая длина (до 32К), любое основание (до 32К), со знаками. Теперь сделать конвертацию займет не более 15 минут.. Если хочешь - могу показать.
andriano
Цитата(Lapp @ 23.12.2007 3:16) *

Дробная часть меньше единицы, целая - больше. Они живут отдельно, независимо. Нет, знаки не могут "переходить".

Я тут на досуге накорябал все четыре действия над вещественными числами smile.gif. Любая длина (до 32К), любое основание (до 32К), со знаками. Теперь сделать конвертацию займет не более 15 минут.. Если хочешь - могу показать.

1. Что знечит "любое основание"? Или числа хранятся в виде текста?
2. 15 минут на конвертацию числа - это сильно даже для IBM PC с ее 4.77. МГц. smile.gif
Lapp
Цитата(andriano @ 23.12.2007 12:13) *
1. Что знечит "любое основание"? Или числа хранятся в виде текста?
andriano, если вступаешь в разговор не в его начале - будь добр, потрудись прочесть предыдущие мессаджи..

Цитата(andriano @ 23.12.2007 12:13) *
2. 15 минут на конвертацию числа - это сильно даже для IBM PC с ее 4.77. МГц. smile.gif
Неудачная шутка - я делал такие вещи еще на Apple-2 (2 МГц, 8 бит) весьма успешно и достаточно быстро smile.gif.
AlexSt
lapp, если не трудно, выложи good.gif
я вот конвертацию уже рабочую слепил, умножение, деление через конвертацию, осталось подумать над сложжением и вычитанием толковым, но выкладывай всё - интересно!
Lapp
Выкладываю.
Предупреждаю:
1. решение не оптимизировано;
2. могут быть ошибки;
3. все действия должны выполняться над числами в одной СС (автоматического контроля за этим нету).
const
L=6;

type
tNum= record
m: array[1..L]of integer;
e,b: integer;
n: boolean;
end;

const
{младшие разряды слева, точка сдвинута на величину e от правого края}
a: tNum= (m:(0,2,1,1,0,0); e:3; b:10; n:false); {это 1.12}
b: tNum= (m:(0,6,5,0,0,0); e:1; b:10; n:true); {это -0.0056}
nill: tNum= (m:(0,0,0,0,0,0); e:0; b:10; n:false); {это 0}

var
c: tNum;

{ Number output }
procedure WrNum(a:tNum);
var
i,k:integer;
begin
with a do begin
if n then Write('-.') else Write(' .');
for i:=L downto 1 do begin
if m[i]<10 then k:=48 else k:=55;
Write(Chr(m[i]+k))
end;
Write('_e',e,'_b',b)
end
end;

procedure Norm(var a:tNum; s:integer);
var
i,j,k:integer;
begin
k:=0;
with a do begin
while (k<L)and(m[L-k]=0) do Inc(k);
if k=L then e:=0
else begin
Dec(k,s);
if k>0 then for i:=L-s downto 1 do begin
j:=i-k;
if j>0 then m[i]:=m[j] else m[i]:=0
end
else if k<0 then for i:=1 to L do begin
j:=i-k;
if j<=L then m[i]:=m[j] else m[i]:=0
end;
Dec(e,k)
end
end
end;

{ Addition, no sign }
procedure Ad(a,b:tNum; var c:tNum);
var
i,d:integer;
begin
Norm(a,1);
Norm(b,1);
if a.m[L-1]=0 then c:=b
else if b.m[L-1]=0 then c:=a
else begin
if a.e>b.e then Norm(b,a.e-b.e+1) else Norm(a,b.e-a.e+1);
d:=0;
for i:=1 to L-1 do begin
d:=a.m[i]+b.m[i]+d;
c.m[i]:=d mod a.b;
d:=d div a.b
end;
c.e:=a.e;
c.b:=a.b
end
end;

{ Substruction, no sign }
procedure Sb(a,b:tNum; var c:tNum);
var
i,d: integer;
f: boolean;
begin
Norm(a,0);
Norm(b,0);
if a.m[L]=0 then begin
c:=b;
c.n:=not b.n
end
else if b.m[L]=0 then begin
c:=a;
c.n:=not a.n
end
else begin
if a.e>b.e then Norm(b,a.e-b.e) else Norm(a,b.e-a.e);
d:=0;
i:=L;
while (i>1)and(a.m[i]=b.m[i]) do Dec(i);
f:=a.m[i]<b.m[i];
for i:=1 to L do begin
if f then d:=b.m[i]-a.m[i]+d+a.b else d:=a.m[i]-b.m[i]+d+a.b;
c.m[i]:=d mod a.b;
d:=d div a.b-1
end;
c.e:=a.e;
c.b:=a.b;
c.n:=f
end
end;

{ Multiplication }
procedure Mul(a,b:tNum; var c:tNum);
var
i,j,s,x: integer;
d: tNum;
f: boolean;
begin
Norm(a,1);
Norm(b,0);
c.n:=a.n xor b.n;
f:=false;
s:=0;
d.b:=a.b;
for j:=1 to L do begin
x:=0;
for i:=1 to L-1 do begin
x:=b.m[j]*a.m[i]+x;
d.m[i]:=x mod a.b;
x:=x div a.b
end;
d.m[L]:=x;
d.e:=s;
Inc(s);
if f then Ad(c,d,c) else begin
c:=d;
f:=true
end
end;
if x>0 then Norm(c,0) else Norm(c,1);
c.e:=a.e+b.e-1
end;

{ Division }
procedure Dv(a,b:tNum; var c:tNum);
var
i,j,k,expa,expb:integer;
d,d0: tNum;
begin
Norm(a,0);
Norm(b,0);
expa:=a.e;
expb:=b.e;
c.n:=a.n xor b.n;
a.e:=0;
b.e:=0;
a.n:=false;
b.n:=false;
for j:=L downto 1 do begin
k:=0;
repeat
Sb(a,b,d);
if d.n then break;
a:=d;
Inc(k);
until false;
c.m[j]:=k;
Dec(b.e)
end;
c.e:=expa-expb+1;
c.b:=a.b
end;

{ Addition, with sign }
procedure Add(a,b:tNum; var c:tNum);
begin
if a.n then if b.n then begin
Ad(a,b,c);
c.n:=true
end
else Sb(b,a,c)
else if b.n then Sb(a,b,c)
else Ad(a,b,c)
end;

{ Substruction, with sign }
procedure Sub(a,b:tNum; var c:tNum);
begin
if a.n then if b.n then Sb(b,a,c)
else begin
Ad(a,b,c);
c.n:=true
end
else if b.n then Ad(a,b,c)
else Sb(a,b,c)
end;

begin
Dv(a,b,c);
WrNum(a); WriteLn;
WrNum(b); WriteLn;
WrNum©; WriteLn;
ReadLn
end.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.