Сложение и умножение больших чисел с использованием динамической памяти - PascalABC.NET
Формулировка задачи:
Задача такова: Используя динамическую память, организовать сложение и умножение двух заданных чисел.
(т.к. данная задача является лишь подготовительной к более сложной, в которой 2 числа задаются заранее, организовывать считывание откуда бы то ни было в этой задаче так же не имеет смысла.)
Мой код:
Проблемы:
1) Глобальные переменные
x
иy
идентичны во всём (кроме, конечно, значения) и проходят через одни и те же процедуры и функции. НО если при изменении переменнойy
программа остаётся работоспособной, то при измененииx
(в частности, при увеличении его до трёхзначного числа и более) в строке 95 обнаруживается ошибка (Ошибка времени выполнения: ссылка на объект не указывает на экземпляр объекта). 2) В функции умножения результат имеет 2 лишних нуля в конце. Я подозреваю, что это либо вызвано инициализацией пустых деков, либо просчетами с переменнымиcount
иcount0
. Но сколько-нибудь полноценно исправить это у меня не вышло. Прошу указать на причины данных ошибок и дать советы по их устранению.
Вопрос больше не актуален, исправила всё самостоятельно.
Решение задачи: «Сложение и умножение больших чисел с использованием динамической памяти»
textual
Листинг программы
type tDigit = class N : Byte; L, R : tDigit; constructor (N_ : Byte; L_ : tDigit := nil; R_ : tDigit := nil); begin (N, L, R) := (N_, L_, R_); if L_ <> nil then L_.R := Self; if R_ <> nil then R_.L := Self; end; end; type bNumber = record Len : Integer; /// Длина числа Left, Right : tDigit; /// Ссылка на начало и конец числа /// Добавление цифры слева procedure LeftDigit(N : Byte); begin Len += 1; Left := New tDigit(N, nil, Left); end; /// Добавление цифры справа procedure RightDigit(N : Byte); begin Len += 1; Right := New tDigit(N, Right, nil); end; /// Создание числа из целого constructor (N : Integer); begin Len := 1; Right := New tDigit(N mod 10); N := N div 10; Left := Right; while N <> 0 do begin LeftDigit(N mod 10); N := N div 10; end; end; /// Создание числа из строки constructor (S : String); begin Len := 1; Right := New tDigit(Ord(S[S.Length])-48); Left := Right; for var Index := S.Length-1 downto 1 do LeftDigit(Ord(S[Index])-48); end; /// Создание из другого длинного числа constructor (n : bNumber); begin Len := 1; Right := New tDigit(n.Right.N); Left := Right; var Cur := n.Right.L; while Cur <> nil do begin LeftDigit(Cur.N); Cur := Cur.L; end; end; /// Преобразование числа в строку function toString : String; override; begin Result := ''; var Cur := Left; while Cur <> nil do (Result, Cur) := (Result + Cur.N.ToString, Cur.R); end; /// Вывод числа function Print : bNumber; begin Write(toString); Result := Self; end; /// Вывод числа с переходом на новую строку function PrintLn : bNumber; begin WriteLn(ToString); Result := Self; end; /// Добавление длинного числа function Add(n : bNumber) : bNumber; begin var d : Byte := 0; var cCur := Right; var nCur := n.Right; // сложим все цифры по самой маленькой длине числа while (cCur <> nil) and (nCur <> nil) do begin d += cCur.N + nCur.N; cCur.N := d mod 10; d := d div 10; cCur := cCur.L; nCur := nCur.L; end; // если во втором числе больше знаков, то нужно добавить его while nCur <> nil do begin d += nCur.N; LeftDigit(d mod 10); d := d div 10; nCur := nCur.L; end; // если в первом числе больше знаков и остался перенос while (cCur <> nil) and (d > 0) do begin d += cCur.N; cCur.N := d mod 10; d := d div 10; cCur := cCur.L; end; // если ещё остался перенос, то и его добавим if d > 0 then LeftDigit(d); Result := Self; end; /// Увеличение числа в 10 раз function Mul10 : bNumber; begin Result := Self; // проверяем на self=0 if (Len = 1) and (Left.N = 0) then Exit; RightDigit(0); end; /// Умножение на длинное число function Mul(n : bNumber) : bNumber; begin Result := Self; // проверяем на self=0 if (Len = 1) and (Left.N = 0) then Exit; // это таблица умножения с 0 по 9 var an : array of bNumber; SetLength(an, 10); an[0] := New bNumber(0); for var i := 1 to 9 do begin an[i] := New bNumber(an[i-1]); an[i].Add(Self); end; // исходное число обнуляем Left := Right; Left.L := nil; Left.N := 0; Len := 1; // проверяем на n=0 if (n.Len = 1) and (n.Left.N = 0) then Exit; // умножаем var Cur := n.Left; repeat Self.Mul10; Self.Add(an[Cur.N]); Cur := Cur.R; until Cur = nil; end; /// Переопределение операций class function operator+(a, b : bNumber) : bNumber; begin Result := New bNumber(a); Result.Add(b); end; class function operator*(a, b : bNumber) : bNumber; begin Result := New bNumber(a); Result.Mul(b); end; class function operator implicit(n : String) : bNumber; begin Result := New bNumber(n); end; class function operator explicit(n : bNumber) : String; begin Result := n.toString; end; end; begin var a := New bNumber(123); WriteLn('a = ' + a.toString); var b := New bNumber('12345'); Write('b = '); b.PrintLn; WriteLn('сумма: ' + a.toString + ' + ' + b.toString + ' = ' + String(a+b)); WriteLnFormat('произведение: {0} x {1} = {2}', a, b, a*b); var b1 := bNumber('12345678901234567890'); var b2 := '98765432109876543210'; WriteLn(String(b1*bNumber(b2))); WriteLn('end.'); end.
Объяснение кода листинга программы
- Объявление типа tDigit и его полей N, L и R.
- Создание конструктора для класса tDigit.
- Объявление методов LeftDigit и RightDigit для класса bNumber.
- Создание конструктора для класса bNumber, который создает число из целого числа.
- Создание конструктора для класса bNumber, который создает число из строки.
- Создание конструктора для класса bNumber, который создает число из другого длинного числа.
- Объявление метода toString для класса bNumber.
- Объявление метода Print для класса bNumber.
- Объявление метода PrintLn для класса bNumber.
- Объявление метода Add для класса bNumber.
- Объявление метода Mul10 для класса bNumber.
- Объявление метода Mul для класса bNumber.
- Объявление оператора + для класса bNumber.
- Объявление оператора * для класса bNumber.
- Объявление оператора implicit для класса bNumber.
- Объявление оператора explicit для класса bNumber.
- Пример использования методов и операторов класса bNumber.
- Создание переменной b1 типа bNumber с текстовым значением '12345678901234567890'.
- Создание переменной b2 типа string с текстовым значением '98765432109876543210'.
- Пример использования метода Mul для переменной b1 и переменной b2.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д