См. также:
В зависимости от прикладных задач, для представления «длинных» чисел используются либо статические векторы (массивы), либо динамические структуры (списки).
Чтобы реализовать базовые арифметические операцие +, −, x, / над «длинными» числами, следует опираться на стандартные методы вычисления сложения/вычитания/умножения «в столбик» и деления «уголком». При этом понадобятся вспомогательные подпрограммы:
Пронумеруем разряды «длинных» чисел, например, ai или bi, и положим M равным основанию системы счисления.
Алгоритм «длинного» сложения основан на методе сложения в «столбик». При этом циклически, начиная с младших разрядов, производится сложение с переносом.
{ Сложение с := a + b } cf := 0; L := max ( length (a), length (b) ); i := 0; while ( i < L ) or ( cf <> 0 ) do begin t := a[i] + b[i] + cf; if M <= t then { c[i] := ( a[i] + b[i] + cf ) mod M } begin { cf := ( a[i] + b[i] + cf ) div M } c[i] := t - M cf := 1; end else begin c[i] := t; cf := 0; end; i := i + 1; end;
Введите неотрицательные целые аргументы a и b:
Вычитание двух неотрицательных чисел также можно реализовать «в столбик».
{ Вычитание с := a - b } L := max ( length (a), length (b) ); sign := false; if a < b then begin swap ( a, b ); sign := true; end i := 0; cf := 0; while ( i < L ) or ( cf <> 0 ) do begin t := b[i] + cf; if a[i] < t then begin c[i] := M + a[i] - t; cf := 1; end else begin c[i] := a[i] - t; cf := 0; end; i := i + 1; end; if sign then inv (c);
Введите неотрицательные целые аргументы a и b:
Для обеспечения работы алгоритмы умножения следует реализовать деление неотрицательного «длинного» числа на 2.
{ Деление на 2 a := a div 2 } cf := 0; i := length (a); while 0 <= i do begin t := a[i] + cf*M; a[i] := t div 2; cf := t mod 2; i := i - 1; end;
Введите неотрицательное целое:
Для реализации «длинного» умножения можно воспользоваться методом разложения произведения ab на сумму вида 2n + q. Для наглядности можно привести следующие тождества:
Тогда алгоритм умножения неотрицательных «длинных» чисел можно выразить через реализованный ранее алгоритм сложения/вычитания и алгоритм деления на 2.
{ Умножение p := a * b } p := 0; if ( a < b ) then { если в качестве b выбрать меньшее число, то эффективность выше } swap (a, b); while 0 < b do begin if b mod 2 = 0 then begin a := a + a; { a := 2*a; } b := b / 2; end else begin b := b - 1; p := p + a; end; end;
Введите неотрицательные целые аргументы a и b:
Деление неотрицательных «длинных» чисел «уголком» выглядит не столь эффектно, как реализованное выше умножение. Реализовать деление более оптимально можете попробовать самостоятельно.
{ Деление p := a div b; q := a mod b; } q := a; { спасаем исходное a, и в q будет остаток от деления } La := length ( q ); Lb := length ( b ); sh := La - Lb; p := 0; while b <= q do begin o := 1; t := shiftr ( q, sh ); if t < b then begin sh := sh - 1; t := shiftr ( q, sh ); o := 0; end; { подбор очередной цифры частного } d := 9; m := b * d; while t < m do begin d := d - 1; m := b * d; end; q := q - shiftl ( m, sh ); p := shiftl ( p, 1 ) + d; if q < b then shiftl ( p, sh ) else shiftl ( p, La - length (q) - o - 1 ); La := length ( q ); end;
Введите неотрицательные целые аргументы a и b: