Contributor: ALEXSANDAR DLABAC
Unit LongNum;
{
лллллллллллллллллллллллллллллллллллллллллллллллллл
лллнммммммммммммммммммммммммммммммммммммммммммолллББ
лллнлл ллолллББ
лллнлл Numbers with up to 255 digits ллолллББ
лллнлл ллолллББ
лллнлл Aleksandar Dlabac ллолллББ
лллнлл (C) 1997. Dlabac Bros. Company ллолллББ
лллнлл ------------------------------ ллолллББ
лллнлл adlabac@urcpg.urc.cg.ac.yu ллолллББ
лллнлл adlabac@urcpg.pmf.cg.ac.yu ллолллББ
лллнлл ллолллББ
лллнпппппппппппппппппппппппппппппппппппппппппполллББ
ллллллллллллллллллллллллллллллллллллллллллллллллллББ
ББББББББББББББББББББББББББББББББББББББББББББББББББ
}
{
This program enables use of a very long signed integer numbers - up to
255 digits. Numbers are in fact strings, so they can be easily writed on
screen/file/printer. If variable LongNumError is set to True, there was an
error during calculations/conversions (overflow, for example).
}
Interface
Var LongNumError : Boolean;
Function MakeLong (Number:longint) : string;
{ Converts longint number to string. }
Function MakeInt (Number:string) : longint;
{ Converts long number to longint, if possible. }
Function Neg (A:string) : string;
{ Returns -A. }
Function Sgn (A:string) : shortint;
{ Returns Signum (A): 1 if A>0, 0 if A=0, -1 if A<0. }
Function FormatLongNumber (Number:string;Digits:byte) : string;
{ Formats long number so it will have given number of digits. If number of
digits is smaller than number size, LongNumError will be True. }
Function Add (A,B:string) : string;
{ Returns A+B. }
Function Subtract (A,B:string) : string;
{ Returns A-B. }
Function Multiple (A,B:string) : string;
{ Returns A*B. }
Function Divide (A,B:string;var Remainder:string) : string;
{ Returns A/B. Remainder is division remaider. }
Function Power (A:string;B:byte) : string;
{ Returns A^B. }
Function Equal (A,B:string) : Boolean;
{ Returns True if A=B. }
Function Greater (A,B:string) : Boolean;
{ Returns True if A>B. }
Function GreaterOrEqual (A,B:string) : Boolean;
{ Returns True if A>=B. }
Implementation
Function Dgt (C:char) : byte;
Var Temp : byte;
Begin
Temp:=0;
If C in ['1'..'9'] then
Temp:=Ord (C)-48;
If not (C in ['-',' ','0'..'9']) then
LongNumError:=True;
Dgt:=Temp
End;
Function MakeLong (Number:longint) : string;
Var Temp : string;
Begin
Str (Number,Temp);
MakeLong:=Temp
End;
Function MakeInt (Number:string) : longint;
Var Temp : longint;
I : byte;
Begin
LongNumError:=(Sgn (Subtract (MakeLong (2147483647),Number))=-1) or
(Sgn (Subtract (Number,MakeLong (-2147483647)))=-1) or
(Number='');
Temp:=0;
If not LongNumError then
Begin
For I:=1 to Length (Number) do
Temp:=Temp*10+Dgt (Number [I]);
Temp:=Temp*Sgn (Number);
End;
MakeInt:=Temp
End;
Function Neg (A:string) : string;
Var Temp : string;
Begin
LongNumError:=False;
Temp:=FormatLongNumber (A,0);
If Temp [1]='-' then
Temp:=Copy (Temp,2,Length (Temp)-1)
else
If Length (Temp)<255 then
Temp:='-'+Temp
else
LongNumError:=True;
Neg:=Temp
End;
Function Sgn (A:string) : shortint;
Var I : byte;
Temp : shortint;
S : string;
Begin
S:=FormatLongNumber (A,0);
Case S [1] of
'-' : Temp:=-1;
'0' : Temp:=0;
else Temp:=1
End;
Sgn:=Temp
End;
Function FormatLongNumber (Number:string;Digits:byte) : string;
Var I : byte;
Temp : string;
Begin
Temp:=Number;
I:=1;
While (I0) and (Temp [1]=' ') do
Temp:=Copy (Temp,2,Length (Temp)-1);
If Temp='' then
Temp:='0';
If Digits>0 then
Begin
While Length (Temp)' ') then
LongNumError:=True;
Temp:=Copy (Temp,Length (Temp)-Digits+1,Digits)
End;
FormatLongNumber:=Temp;
End;
Function Add (A,B:string) : string;
Var Sign, Factor, SgnA, SgnB, N : shortint;
Transf, Sub, I : byte;
N1, N2, Temp : string;
Error : Boolean;
Begin
Error:=False;
SgnA:=Sgn (A);
SgnB:=Sgn (B);
If SgnA*SgnB=0 then
Begin
If Sgn (A)=0 then
Temp:=B
else
Temp:=A
End
else
Begin
If SgnA=-1 then
N1:=Neg (A)
else
N1:=A;
If SgnB=-1 then
N2:=Neg (B)
else
N2:=B;
While Length (N1)0 then
Begin
Sign:=SgnA;
Factor:=1;
End
else
Begin
If N1=N2 then
Sign:=1
else
Begin
If N1>N2 then
Sign:=SgnA
else
Begin
Sign:=SgnB;
Temp:=N1;
N1:=N2;
N2:=Temp
End
End;
Factor:=-1
End;
Temp:='';
Transf:=0;
Sub:=0;
For I:=Length (N1) downto 1 do
Begin
N:=Transf+(10+Dgt (N1 [I])-Sub) mod 10+Factor*Dgt (N2 [I]);
Transf:=0;
Sub:=0;
If N<0 then
Begin
Sub:=1;
Inc (N,10)
End
else
If N>=10 then
Begin
Transf:=1;
Dec (N,10)
End;
Temp:=Chr (N+48)+Temp;
End;
If ((Length (Temp)=255) and (Transf>0)) or (Sub>0) then
Error:=True
else
Begin
If Transf>0 then
Temp:=Chr (Transf+48)+Temp;
If Sign=-1 then
Temp:=Neg (Temp)
End
End;
Temp:=FormatLongNumber (Temp,0);
If Error then
LongNumError:=True;
Add:=Temp
End;
Function Subtract (A,B:string) : string;
Var Temp : string;
Begin
Subtract:=Add (A,Neg (B))
End;
Function Multiple (A,B:string) : string;
Var Sign, SgnA, SgnB, N : shortint;
I, J, D, Transf : byte;
N1, N2, Temp, S : string;
Error : Boolean;
Begin
Error:=False;
SgnA:=Sgn (A);
SgnB:=Sgn (B);
Sign:=SgnA*SgnB;
If SgnA=-1 then
N1:=Neg (A)
else
N1:=A;
If SgnB=-1 then
N2:=Neg (B)
else
N2:=B;
If Sign=0 then
Temp:='0'
else
Begin
N1:=FormatLongNumber (N1,0);
If LongNumError then
Error:=True;
N2:=FormatLongNumber (N2,0);
If LongNumError then
Error:=True;
Temp:='0';
For J:=Length (N2) downto 1 do
Begin
D:=Dgt (N2 [J]);
Transf:=0;
S:='';
For I:=1 to Length (N2)-J do
S:=S+'0';
For I:=Length (N1) downto 1 do
Begin
N:=Transf+D*Dgt (N1 [I]);
If Length (S)=255 then
Error:=True;
S:=Chr (N mod 10+48)+S;
Transf:=N div 10
End;
If Transf>0 then
If Length (S)=255 then
Error:=True
else
S:=Chr (Transf+48)+S;
Temp:=Add (Temp,S);
If LongNumError then
Error:=True
End
End;
If Sign=-1 then
Temp:=Neg (Temp);
Temp:=FormatLongNumber (Temp,0);
If Error then
LongNumError:=True;
Multiple:=Temp
End;
Function Divide (A,B:string;var Remainder:string) : string;
Var Sign, SgnA, SgnB : shortint;
I, J : byte;
N1, N2, Temp, S1, S2 : string;
Error : Boolean;
Begin
Error:=False;
SgnA:=Sgn (A);
SgnB:=Sgn (B);
Sign:=SgnA*SgnB;
If SgnA=-1 then
N1:=Neg (A)
else
N1:=A;
If SgnB=-1 then
N2:=Neg (B)
else
N2:=B;
N1:=FormatLongNumber (N1,0);
If LongNumError then
Error:=True;
N2:=FormatLongNumber (N2,0);
If LongNumError then
Error:=True;
If not GreaterOrEqual (N1,N2) then
Begin
Temp:='0';
If SgnA=-1 then
Remainder:=Neg (N1)
else
Remainder:=N1
End
else
Begin
Temp:='';
S1:=N1;
For I:=1 to Length (N1)-Length (N2)+1 do
Begin
S2:=Copy (S1,1,I+Length (N2)-1);
J:=9;
While Greater (Multiple (N2,Chr (J+48)),S2) do
Dec (J);
Temp:=Temp+Chr (J+48);
S1:=Subtract (S2,Multiple (N2,Chr (J+48)))+Copy (S1,I+Length (N2),Length (S1)-I-Length (N2)+1);
While Length (S1)0
End;
Function GreaterOrEqual (A,B:string) : Boolean;
Begin
GreaterOrEqual:=Sgn (Subtract (A,B))>=0
End;
End.
Program LongTest;
Uses Crt, LongNum;
Var L : longint;
S, Remainder : string;
Begin
ClrScr;
S:=MakeLong (-198371298);
If LongNumError then
Writeln ('Error in calculations.')
else
Write (S);
L:=MakeInt (S);
If LongNumError then
Writeln ('Error in calculations.')
else
Writeln (' = ',L);
Writeln;
S:=Add ('1234567890','987654321');
If LongNumError then
Writeln ('Error in calculations.')
else
Writeln ('1234567890 + 987654321 = ',S);
Writeln;
S:=Multiple ('-123','456');
If LongNumError then
Writeln ('Error in calculations.')
else
Writeln ('-123 * 456 = ',S);
Writeln;
S:=Divide ('12345','-456',Remainder);
If LongNumError then
Writeln ('Error in calculations.')
else
Writeln ('12345 / (-456) = ',S,' [',Remainder,']');
Writeln;
S:=Power ('-1234567890',5);
If LongNumError then
Writeln ('Error in calculations.')
else
Writeln ('-1234567890^5 = ',S)
End.