есть отличный программный код для умножения и сложения двух чисел в разл системах(целых через строковый тип) помогите реализовать такие же функции для вычитания и деления(это самое главное!))), ещё желательно чтобы все функции решали задачи и для вещественных чисел, сдавать через неделю( вот код:
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
6.12.2007 7:06
AlexSt, пожалуйста, не дублируй темы.
!
Два дубля этой темы удалены.
AlexSt
14.12.2007 14:51
помогите модернизировать алгоритм конвертации чисел(чтобы конвертировал числа с дробной частью), или на словах хотя бы напишите что делать.
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
15.12.2007 3:38
что, никто не может объяснить даже на словах как замутить с дробной частью???java script:emoticon(':blink:', 'smid_2')
Lapp
15.12.2007 14:04
Послушай, AlexSt, а сам-то ты что-нибудь сделал?.. Насколько я понял, ты притащил чужой код и просишь нас изменить его для тебя. А кому от этого какая польза? Только та, что ты зачет сдашь?
Твоя задача, на самом деле, интересная и не очень простая. Но копаться в чужом коде лично я не хочу. Лично мне удобнее и быстрее было бы написать свою прогу. И тебе я рекомендую сделать именно это. С нуля. И если ты решишься на это - помощь я тебе гарантирую (как минимум - свою). А так - какой смысл? Ты правда думаешь, что мне так хочется, чтоб ты сдал свой зачет или что там у тебя?.. Вот научить тебя я хочу. Честно.
Кстати, добавление возможности вещественных чисел к этой программе - совсем не такая простая вещь. Например, для конвертации тебе понадобится деление. Если ты все же хочешь переделывать эту программу, разберись, как она работает. Я готов отвечать на твои вопросы (по делу).
AlexSt
15.12.2007 15:19
в проге я разобрался, сам сделал вычитание, хочу ща сделать конвертацию без деления... будут вопросы - отпишусь
Lapp
15.12.2007 18:50
Цитата(AlexSt @ 15.12.2007 11:19)
в проге я разобрался, сам сделал вычитание, хочу ща сделать конвертацию без деления...
Вот это мне нравится . Буду следить за темой.
Добавлено через 18 мин. Некоторые соображения общего характера.. Из истории арифметики .
Как появились числа? Просто люди стали считать - пальцы, коров.. Какие это были числа? Натуральные (то есть 1, 2, 3...) Потом появилось сложение. Многократное сложение - это умножение. Сначала система счисления была римская - в ней считать неудобно. Потом появилась десятичная запись. Что она собой представляет? Сумму произведений цифр на основание системы.
Теперь остановимся и посмотрим на ту прогу, которую ты привел. Что там есть? Мне видится, что главное там - конвертация. Для нее нужно уметь умножать (цифры на основание). Для умножения надо уметь складывать. Чувствуешь аналогию с историческим процессом?
Идем дальше. Появилось вычитание - как действие, обратное сложению. Вычитание повлекло расширение натуральных чисел, добавление к ним нуля и отрицательных чисел. Что такое число "-5"? Это результат операции "0-5". То есть отрицательные числа просто заменили длинную запись (операцию) на короткую (отрицательное число). (попутно вопрос: ты ввел отрицательные числа, когда сделал вычитание? без этого нельзя)
Наконец, появилось действие, обратное умножению - деление. Оно также повлекло за собой расширение понятия числа - появились дробные числа. Что такое 1/5? Это результат операции 1:5 - то есть снова просто укороченная запись, а по сути одно и то же. Как видишь, дробные числа не бывают без деления .
Но я буду рад, если ты мне докажешь обратное
AlexSt
16.12.2007 1:24
ок, только что весьма надёжно получилось сделать умножение с дробной частью, думаю сам смогу сделать и вычитание, для деления хочу перевести числа в десятичную разделить и перевести обратно в нужную сс. остаётся только конвертация чисел с дробной частью... я бы хотел узнать как вообще должна вести себя запятая при конвертации в другую сс?
AlexSt
16.12.2007 14:13
и ещё там есть ф-ция преконверт, гре я пытался сделать перевод в др. сс с запятой, но нажимая выполнить прога виснет( почему?
AlexSt
16.12.2007 18:13
и ещё, под каким номером находится shift и space, в книге не могу найти(, знаю enter - #13, backspace - #8...
andriano
16.12.2007 18:44
Пробел - #20, у Shift кода нет - это клавиша-модификатор. Если в DOS, то можно определить ее нажатие, анализируя область данных BIOS по смещению $17 и $18.
AlexSt
17.12.2007 1:26
спасибо за подсказочку , сегодня за целый день наваял код по конвертированию в др сс с дробной частью, но он работает некорректно, может кто сможет найти ошибку? - ф-ция преконверт (у неё в подопечных ф-ция конверт для перевода целой части)
function preConvert (Num1, SetIn, SetOut: String): String; var
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
18.12.2007 13:06
Цитата(AlexSt @ 16.12.2007 21:26)
наваял код по конвертированию в др сс с дробной частью, но он работает некорректно, может кто сможет найти ошибку? - ф-ция преконверт (у неё в подопечных ф-ция конверт для перевода целой части)
Видимо, не в подопечных, а в подручных..
Посмотрел я твой код.. Если честно - до конца не разобрался, но у меня есть подозрение, что это не нужно.
Хотя тут сайт про Паскаль, по-русски иногда говорить тоже желательно . Пожалуйста, опиши свою идею по переводу словами. Тогда разбирать твою прогу будет намного проще. Заранее скажу, что если она (основная идея) состоит в том, чтобы разделить число на целую и дробную части, перевести их по отдельности в другую СС (систему счисления, так правильно, не "исчисления"), а потом снова слепить вместе через десятичную точку (а мне показалось, что ты хочешь делать именно так), то вынужден тебя разочаровать - этот путь неверный. Он неверен в корне, а не в отдельных деталях, так что, я думаю, его и подправить нельзя . Именно поэтому я прекратил разбор твоего кода, когда заподозрил это.
Пожалуйста, прежде чем предлагать код для выискивания ошибок, говори хотя бы в нескольких словах алгоритм. Ладно? Если хочешь, можем начать обсуждение работоспособного алгоритма.
AlexSt
19.12.2007 1:25
а какие ещё есть варианты кроме как "разделить" и "слепить"? у меня только такая идея и была...(
Lapp
19.12.2007 12:48
Цитата(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
Так что тебе понадобится деление. Я бы на твоем месте все сделал заново, без той проги.. Ничего особо сложного, а путаницы меньше. Время есть?
Гость
19.12.2007 15:16
спасибо, наверно так и сделаю, деление только как...
Lapp
19.12.2007 15:42
Цитата(Гость @ 19.12.2007 11:16)
спасибо, наверно так и сделаю, деление только как...
Можно просто обычным уголком . Деление a/b это есть нахождение корня уравнения a=b*x. В оригинале это делается подбором. Способ деления уголком - это и есть подбор (вспомни, каждую цифру приходится подбирать).
Вообще, если хочешь подойти серьезно, рекомендую почитать Кнута.
Я помогу с делением. Только чуть позже.. спать пора
AlexSt
19.12.2007 23:02
Цитата
обычным уголком
))) если есть алгоритм или знаешь где есть отпишись как проснёшся по поводу времени - его уже нет, курсовую лучше всего было бы сдать завтра (к отчёту ещё и не приступал) Кнута почитать не успею
AlexSt
19.12.2007 23:44
кстати, к свелению у меня прога на делфы... я думаю целесообразно буит изменить ф-цию конверт используя "правило уголка"... жду, жду, жду....
Lapp
21.12.2007 12:25
Цитата(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
21.12.2007 16:32
ого!, здо'рово! попытаюсь разобраться, вот хотел ещё узнать при конвертации если количество знаков в дробной части увеличивается часть из них может перейти в целую часть числа? зависит ли положение запятой от того в большую сс переводишь число или в меньшую? я кстати сделал уголок, но вот запятая всё косячит не знаю пока, если пойму возьмусь за твою идею)
Lapp
23.12.2007 7:16
Цитата(AlexSt @ 21.12.2007 12:32)
хотел ещё узнать при конвертации если количество знаков в дробной части увеличивается часть из них может перейти в целую часть числа?
Дробная часть меньше единицы, целая - больше. Они живут отдельно, независимо. Нет, знаки не могут "переходить".
Я тут на досуге накорябал все четыре действия над вещественными числами . Любая длина (до 32К), любое основание (до 32К), со знаками. Теперь сделать конвертацию займет не более 15 минут.. Если хочешь - могу показать.
andriano
23.12.2007 16:13
Цитата(Lapp @ 23.12.2007 3:16)
Дробная часть меньше единицы, целая - больше. Они живут отдельно, независимо. Нет, знаки не могут "переходить".
Я тут на досуге накорябал все четыре действия над вещественными числами . Любая длина (до 32К), любое основание (до 32К), со знаками. Теперь сделать конвертацию займет не более 15 минут.. Если хочешь - могу показать.
1. Что знечит "любое основание"? Или числа хранятся в виде текста? 2. 15 минут на конвертацию числа - это сильно даже для IBM PC с ее 4.77. МГц.
Lapp
23.12.2007 19:40
Цитата(andriano @ 23.12.2007 12:13)
1. Что знечит "любое основание"? Или числа хранятся в виде текста?
andriano, если вступаешь в разговор не в его начале - будь добр, потрудись прочесть предыдущие мессаджи..
Цитата(andriano @ 23.12.2007 12:13)
2. 15 минут на конвертацию числа - это сильно даже для IBM PC с ее 4.77. МГц.
Неудачная шутка - я делал такие вещи еще на Apple-2 (2 МГц, 8 бит) весьма успешно и достаточно быстро .
AlexSt
25.12.2007 12:39
lapp, если не трудно, выложи я вот конвертацию уже рабочую слепил, умножение, деление через конвертацию, осталось подумать над сложжением и вычитанием толковым, но выкладывай всё - интересно!
Lapp
25.12.2007 19:58
Выкладываю. Предупреждаю: 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;