L'utilisation du type integer dans Delphi limite les capacités de calcul en raison du domaine de définition de ce type (de -2147483648 à 2147483647).
Il peux arriver qu'on ait besoin d'effectuer des opérations en dehors de ce domaine. L'utilisation des tableaux pour stocker des nombres permet d'utiliser des nombres possédant jusqu'à 2 147 483 647 chiffres (taille maximale d'un tableau ; représente un nombre de 2Go).
Le problème, c'est que les opérateurs mathématiques ne fonctionnent plus sur ce type de nombre. C'est pour cette raison qu'il faut recoder soi-même ses propres fonctions de calculs comme la multiplication, l'addition, la soustraction, etc.
J'ai recodé quelques-unes des principales fonctions usuelles en utilisant des "strings" comme tableaux de stockage.
Les algorithmes ci-dessous ne fonctionnent que sur les entiers positifs.
Source / Exemple :
function suppr_zero (chaine : string) : string;
var
i : integer;
begin
i := 1;
while (i <= length(chaine)-1) and (chaine[i] = '0') do
begin
inc(i);
end;
while i <= length(chaine) do
begin
result := result + chaine[i];
inc(i);
end;
end;
function multiplication_infini (x, y : String) : String;
var
swap : String;
retenue, temp : integer;
i, j, position : integer;
begin
if length(x) < length(y) then
begin
swap := x;
x := y;
y := swap;
end;
i := 1;
retenue := 0;
result := '';
while i <= (length(x)+length(y)) do
begin
result := result +'0';
inc(i);
end;
i := length(x);
while i >= 1 do
begin
position := length(result)-(length(x)-i);
j := length(y);
while j >= 1 do
begin
temp := strtoint(result[position]) + strtoint(x[i]) * strtoint(y[j]) + retenue;
retenue := temp div 10;
result[position] := (inttostr(temp mod 10))[1];
dec(j);
dec(position);
end;
while retenue > 0 do
begin
temp := strtoint(result[position]) + retenue;
retenue := temp div 10;
result[position] := (inttostr(temp mod 10))[1];
dec(position);
end;
dec(i);
end;
result := suppr_zero(result);
end;
function addition_infini (x, y : String) : String;
var
swap : String;
retenue, temp : integer;
i, j, position : integer;
begin
if length(x) < length(y) then
begin
swap := x;
x := y;
y := swap;
end;
i := 1;
retenue := 0;
result := '';
while i <= (length(x)+1) do
begin
result := result +'0';
inc(i);
end;
i := length(x);
j := length(y);
while i >= 1 do
begin
position := length(result)-(length(x)-i);
if j >=1 then
begin
temp := strtoint(result[position]) + strtoint(x[i]) + strtoint(y[j]) + retenue;
dec(j);
end
else
begin
temp := strtoint(result[position]) + strtoint(x[i]) + retenue;
end;
retenue := temp div 10;
result[position] := (inttostr(temp mod 10))[1];
dec(position);
while retenue > 0 do
begin
temp := strtoint(result[position]) + retenue;
retenue := temp div 10;
result[position] := (inttostr(temp mod 10))[1];
dec(position);
end;
dec(i);
end;
result := suppr_zero(result);
end;
function soustraction_infini (x, y : String) : String;
var
retenue, i, j, temp : integer;
begin
if length(x) < length(y) then
begin
result := '0';
exit;
end;
i := 1;
retenue := 0;
result := '';
while i <= (length(x)) do
begin
result := result +'0';
inc(i);
end;
i := length(x);
j := length(y);
while (j >= 1) do
begin
if strtoint(x[i]) < strtoint(y[j]) + retenue then
begin
result[i] := inttostr(strtoint(x[i]) + 10 - (strtoint(y[j]) + retenue))[1];
retenue := 1;
end
else
begin
result[i] := inttostr(strtoint(x[i]) - (strtoint(y[j]) + retenue))[1];
retenue := 0;
end;
dec(j);dec(i);
end;
while (i >= 1) do
begin
temp := strtoint(x[i]) - retenue;
if temp = -1 then
begin
retenue := 1;
temp := 9;
end
else
begin
retenue := 0;
end;
result[i] := inttostr(temp)[1];
dec(i);
end;
result := suppr_zero(result);
end;
//y est limité a 2 millards et quelques.
function puissance_infini (x, y : string) : string;
begin
result := '1';
if y <>'0' then
begin
result := x;
y := soustraction_infini(y, '1');
end;
while (y<>'0') do
begin
if ((strtoint(y) mod 2) = 1) then result := multiplication_infini(result,x);
//normalemnt on devrait mettre "y := division_infini(y,'2');", mais le problème c'est que la division infini utilise puissance_infini :(
y := inttostr(strtoint(y) div 2);
if (y<>'0') then result := multiplication_infini(result,result);
end;
end;
procedure inc_infini(var a : string);
begin
a := addition_infini(a, '1');
end;
procedure dec_infini(var a : string);
begin
a := soustraction_infini(a, '1');
end;
function division_infini (x, y : string) : string;
var
a, c, position, base, temp : string;
i, j : integer;
begin
base := '10';
result := '0';
c := '1';
j := length(y);
while (length(x) > length(y)) or (x >= y) do
begin
i := 1;
a := '';
while i <= j do
begin
a := a + x[i];
inc(i);
end;
c := '1';
temp := y;
while (length(temp) < length(a)) or (temp <= a) do
begin
inc_infini(c);
temp := multiplication_infini(c, y);
end;
dec_infini(c);
position := inttostr(length(x)-j);
temp := multiplication_infini(c, y);
temp := multiplication_infini(temp, puissance_infini(base, position));
temp := soustraction_infini(x, temp);
j := j-(length(x)-length(temp))+1;
x := temp;
result := result + c;
end;
result := suppr_zero(result);
end;
function modulo_infini (x, y : string) : string;
begin
result := soustraction_infini(x, multiplication_infini(division_infini(x, y), y));
end;
Conclusion :
La plupart de ces fonctions ne sont pas "belles" algorithmiquement, mais cela donne une idée de l'utilisation des tableaux pour effectuer des opérations mathématiques.
Je mettrais surement le code à jour pour implémenter d'autres fonctions du meme genres et pour améliorer celles déjà présentes.
Si vous voyez des erreurs ou des améliorations à effectuer (il y en a un paquet !!), n'hésitez pas à me prévenir.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.