Unit LongNum; { лллллллллллллллллллллллллллллллллллллллллллллллллл лллнммммммммммммммммммммммммммммммммммммммммммолллББ лллнлл ллолллББ лллнлл Numbers with up to 255 digits ллолллББ лллнлл -- New functions and bug fixes -- ллолллББ лллнлл ллолллББ лллнлл 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. } Interface Function LongNumError : Boolean; { Returns the status of last operations performed. If there was an error in calculations (overflow, for example), since LongNumError previous call, True will be returned. } Function MakeLong (Number:longint) : string; { Converts longint number to string. } Function MakeInt (Number:string) : longint; { Converts long number to longint, if possible. } Function FormatLongNumber (Number:string;Digits:byte) : string; { Formats long number so it will have given number of digits. If number of digits is zero the number will be represented with as less as possible digits. Otherwise, if number of digits is smaller than number size, LongNumError will return True. } 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 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 Square (A:string) : string; { Returns A^2. } Function SquareRoot (A:string) : string; { Returns Sqrt (A). If negative value is given, square root of absolute value will be returned, and LongNumError will return True. } Function LongToHex (A:string) : string; { Returns hexadecimal value of A. } Function HexToLong (A:string) : string; { Returns decimal value of A, where A is hexadecimal value. } 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 Var LongNumErrorFlag : Boolean; Function LongNumError : Boolean; Var Temp : Boolean; Begin Temp:=LongNumErrorFlag; LongNumErrorFlag:=False; LongnumError:=Temp End; 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 LongNumErrorFlag:=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; Flag : Boolean; Begin Flag:=(Sgn (Subtract (MakeLong (2147483647),Number))=-1) or (Sgn (Subtract (Number,MakeLong (-2147483647)))=-1) or (Number=''); Temp:=0; If Flag then LongNumErrorFlag:=True else Begin For I:=1 to Length (Number) do Temp:=Temp*10+Dgt (Number [I]); Temp:=Temp*Sgn (Number); End; MakeInt:=Temp End; Function FormatLongNumber (Number:string;Digits:byte) : string; Var I : byte; Sign, Temp : string; Begin Temp:=Number; I:=1; Sign:=''; Repeat While (I=Length (Temp)) or (Temp [I] in ['1'..'9','A'..'F']); While (Length (Temp)>0) and (Temp [1]=' ') do Temp:=Copy (Temp,2,Length (Temp)-1); If Temp='' then Temp:='0'; If Temp<>'0' then Temp:=Sign+Temp; If Digits>0 then Begin While Length (Temp)' ') then LongNumErrorFlag:=True; Temp:=Copy (Temp,Length (Temp)-Digits+1,Digits) End; FormatLongNumber:=Temp End; Function Neg (A:string) : string; Var Temp : string; Begin Temp:=FormatLongNumber (A,0); If Temp [1]='-' then Temp:=Copy (Temp,2,Length (Temp)-1) else If Length (Temp)<255 then Temp:='-'+Temp else LongNumErrorFlag:=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 Add (A,B:string) : string; Var Sign, Factor, SgnA, SgnB, N : shortint; Transf, Sub, I : byte; N1, N2, Temp : string; Begin 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; If Dgt (N1 [I])-Sub<0 then Sub:=1 else 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 LongNumErrorFlag:=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); 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; Begin 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); N2:=FormatLongNumber (N2,0); 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 LongNumErrorFlag:=True; S:=Chr (N mod 10+48)+S; Transf:=N div 10 End; If Transf>0 then If Length (S)=255 then LongNumErrorFlag:=True else S:=Chr (Transf+48)+S; Temp:=Add (Temp,S) End End; If Sign=-1 then Temp:=Neg (Temp); Temp:=FormatLongNumber (Temp,0); 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; Begin 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); N2:=FormatLongNumber (N2,0); 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; Begin LongNumErrorFlag:=False End. { ---------------------- Demo program ---------------------- } Program LongTest; Uses Crt, LongNum; Var L : longint; S1, S2, Remainder : string; Begin ClrScr; S1:=MakeLong (-198371298); If LongNumError then Writeln ('Error in calculations.') else Write (S1); L:=MakeInt (S1); If LongNumError then Writeln ('Error in calculations.') else Writeln (' = ',L); Writeln; S1:=Add ('1234567890','987654321'); If LongNumError then Writeln ('Error in calculations.') else Writeln ('1234567890 + 987654321 = ',S1); Writeln; S1:=Multiple ('-123','456'); If LongNumError then Writeln ('Error in calculations.') else Writeln ('-123 * 456 = ',S1); Writeln; S1:=Divide ('12345','-456',Remainder); If LongNumError then Writeln ('Error in calculations.') else Writeln ('12345 / (-456) = ',S1,' [',Remainder,']'); Writeln; S1:=Power ('-1234567890',5); If LongNumError then Writeln ('Error in calculations.') else Writeln ('-1234567890^5 = ',S1); Writeln; S1:=Square ('-1234567890'); If LongNumError then Writeln ('Error in calculations.') else Writeln ('-1234567890^2 = ',S1); Writeln; S2:=S1; S1:=SquareRoot (S1); If LongNumError then Writeln ('Error in calculations.') else Writeln ('Sqrt (',S2,') = ',S1); Writeln; S1:=LongToHex ('1234567890987654321'); If LongNumError then Writeln ('Error in calculations.') else Writeln ('1234567890987654321 = ',S1,'H'); Writeln; S2:=S1; S1:=HexToLong (S1); If LongNumError then Writeln ('Error in calculations.') else Writeln (S2,'H = ',S1) End.