(* Programa que permite sumar numeros naturales de hasta cien dígitos de longitud *)
(* utilizando un array con tope *)
PROGRAM Aritnat(input,output);
CONST
MaxDig = 100; (* Constante que indica longitud maxima del numero *)
TYPE
Digito = 0..9; (* en cada celda del array se introducirán digitos del cero al nueve *)
Natural = RECORD
digitos: ARRAY [1..MaxDig] OF Digito;
tope: 0..MaxDig;
END;
VAR
a, b, c:Natural; (* a y b son los sumandos, c es el resultado de la suma *)
suma, acarreo, i, digit:integer; (* Variables para procesar los datos *)
temp:integer;
BEGIN
(* Lectura de los números a sumar *)
writeln('Ingrese el primer numero:');
readln(digit); (* Se ingresa el primer digito *)
a.tope := 0; (* Se inicializa el tope *)
WHILE (digit IN [0..9]) AND ((a.tope < MaxDig) OR (a.tope = MaxDig)) DO
BEGIN (* Mientras el digito que se ingrese pertenesca al subrango 0..9 y mientras no se haya terminado el array *)
a.tope := a.tope + 1; (* Se incrementa en uno el tope del array *)
a.digitos[a.tope] := digit; (* Se almacena el digito en la celda correspondiente *)
readln(digit) (* Se lee el siguiente digito *)
END;
(* se solicita ingresar el segundo numero *)
writeln('Ingrese el segundo numero:');
readln(digit); (* Se lee el primer digito *)
b.tope := 0; (* Se inicializa el tope *)
WHILE (digit IN [0..9]) AND ((b.tope < MaxDig) OR (b.tope = MaxDig)) DO
BEGIN (* Mientras pertenesca al intervalo 0..9 y no se termine el array *)
b.tope := b.tope + 1; (* Se incrementa el tope *)
b.digitos[b.tope] := digit; (* Se almacena el digito en la celda correspondiente *)
readln(digit) (* Se lee el siguiente digito *)
END;
(* Si un array tiene mas digitos que otro, entonces al que tiene menos hay que agregarle ceros al principio *)
(* Hasta que ambos tengan la misma longitud, de esa manera la suma se hará con mayor facilidad *)
IF (a.tope > b.tope) THEN BEGIN
FOR i := b.tope DOWNTO 1 DO BEGIN
temp := b.digitos[i+(a.tope-b.tope)];
b.digitos[i+(a.tope-b.tope)] := b.digitos[i];
b.digitos[i] := temp;
b.tope := b.tope + (a.tope - b.tope);
END; (* FOR *)
FOR i := 1 TO (a.tope - b.tope) DO
b.digitos[i] := 0;
END (* if *)
ELSE IF (b.tope > a.tope) THEN BEGIN
FOR i := a.tope DOWNTO 1 DO BEGIN
temp := a.digitos[i+(b.tope-a.tope)];
a.digitos[i+(b.tope-a.tope)] := a.digitos[i];
a.digitos[i] := temp;
a.tope := a.tope + (b.tope-a.tope);
END; (* FOR *)
FOR i := 1 TO (b.tope - a.tope) DO
a.digitos[i] := 0;
END; (* ELSE IF *)
c.tope := 0;
FOR i := 1 TO (a.tope) DO BEGIN
c.tope := c.tope + 1;
c.digitos[i] := 0
END;
(* Ahora se le indicará a la máquina que sume los arreglos a y b como lo hacíamos en la escuela: digito a digito *)
(* empezando por las unidades y de derecha a izquierda *)
(* hay que considerar también el acarreo de las decenas, que por defecto, *)
(* se inicializa en cero *)
acarreo := 0;
FOR i := (a.tope) DOWNTO 1 DO BEGIN
suma := a.digitos[i] + b.digitos[i] + acarreo;
IF (i = 1) AND (suma DIV 10 = 1) THEN BEGIN (* caso excepcional: si al sumar el primer digito de a con el de b, el resultado es 10 o más, *)
c.digitos[c.tope+1] := c.digitos[c.tope]; (* entonces, al array c se le agrega una cifra más al principio: la cifra del acarreo *)
c.tope := c.tope + 1;
c.digitos[2] := suma MOD 10;
c.digitos[1] := suma DIV 10
END (* IF *)
ELSE BEGIN (* sino, entonces sumamos cifra con cifra y almacenamos las unidades en la celda del array c, y las decenas que sobren en acarreo *)
c.digitos[i] := suma MOD 10;
acarreo := suma DIV 10
END; (* ELSE *)
END; (* FOR *)
(* Para terminar, mostramos el resultado de la suma en pantalla *)
FOR i := 1 TO (c.tope) DO
write(c.digitos[i]);
readln(i);
END.