Program for number conversion, bases 2..72
Author Message Program for number conversion, bases 2..72

Program BaseConversion;

An input numeric symbol string is converted to an integer value.
The integer value is then converted to a numeric symbol string
as the output. The highest symbol that can be entered from the
keyboard is '~' which limits the maximum input base to 72.
Although you could make the output base higher, I didn't.
For input bases > 42, 'a' = 42 and 'A' = 10. For keyboard
entry convenience, all lower case chars are converted to upper
case for input bases < 43. The numerous range checks performed
in function StrToInt while converting a symbol string to an
integer is to avoid exceeding LongInt.

A tutorial on base conversion was posted to this newsgroup near
the same time. Servers being what they are, if you need a copy,
send email to above. }

CONST
bel = Chr(7);
Big10 = 2147483647;   (* highest positive LongInt *)
Alpha = ord('A') - 10;

TYPE
Str32 = String;   (* optional, saves heap space *)

VAR
IntVal:LongInt;      (* allows values up to 2,147,483,647 *)
BaseIn, BaseOut:Integer;
SymStrIn, SymStrOut:Str32;(*symbol strings used as input and output*)
BasesOK:Boolean;

Function SymVal(DigCh:Char):Integer;
(* Error checking to avoid wrong symbol values done later *)
Begin
Case DigCh of
'0'..'9' : SymVal := ord(DigCh) - ord('0');
'A'.. '~': SymVal := ord(DigCh) - Alpha;
End;
End;

Function DigitSymbol(ChVal:Integer):Char;
(* ChVal has already been screened for errors *)
Begin
Case ChVal of
0..9 : DigitSymbol := Chr(ord('0') + ChVal);
10..71 : DigitSymbol := Chr(Alpha + ChVal);
End;
End;

Function IntToStr(Num:LongInt; BasOut:Integer):Str32;
VAR  n:Integer;
NumCh:Char;
Accum:Str32;
Begin
Accum := '';
While Num > 0 Do
Begin
n  := Num mod BasOut;   (* value of BasOut digit *)
NumCh := DigitSymbol(n);  (* symbol for digit value *)
Accum := Concat(NumCh, Accum); (* NumCh to front of Accum *)
Num := Num div BasOut;   (* Num := what's left to convert *)
End;
IntToStr := Accum;(* may look like a number, but it's a string *)
End;

Function StrToInt(s:Str32; BasIn:Integer):LongInt;
Var   DigPos:Integer;
Buff, DigVal, PosVal, HiLim:LongInt;
InRange:Boolean;
Begin
InRange := True;    PosVal := 1;  (* rightmost position value *)
Buff := 0;      DigPos := Length(s); (* rightmost position *)

While (DigPos > 0) and (InRange) do
Begin
HiLim := Round(Big10 / PosVal);  (* highest multiplier *)

DigVal := SymVal(s[DigPos]);
If (DigVal >= BasIn) or (DigVal < 0) then  (* error *)
Begin
StrToInt := -1; (* downstream err flag *)
EXIT;  (* this function *)
End;

InRange := DigVal <= HiLim;   (* range check *)
If InRange then DigVal := DigVal * PosVal;
(* highest addend range check *)
InRange := (InRange) AND (IntVal <= Big10 - Buff);
If InRange then Buff := Buff + DigVal;

Dec(DigPos);
If DigPos > 0 then
Begin
(* the last range check in this pass! *)
InRange := (InRange) AND (BasIn <= HiLim);
If InRange then PosVal :=  PosVal * BasIn;
End;
End;

If InRange then StrToInt := Buff
Else
Begin
Write(bel, 'Operation exceeded ', Big10);
StrToInt := 0;
Writeln;
End;
End;

Procedure DisplayRange(B_in:Integer);
VAR   UpperLim:Str32;
Sval:Integer;
Begin
If B_in > 42 then Writeln('Lower case <> upper case symbols!');
For Sval := 0 to B_in - 1 do Write(DigitSymbol(Sval));
Writeln;
Write('Use only above symbols. ');
UpperLim := IntToStr(Big10, B_in);
Writeln('Upper limit is ', UpperLim);   Writeln;
End;

Procedure GetNumber(VAR NStr:Str32);
(* for clarity global, variables BaseIn, BaseOut are used *)
VAR m, Dval:Integer;
OK:Boolean;
Begin
Repeat (* until number is OK *)
Write('Base ', BaseIn, ' to ', BaseOut);
Writeln(', Enter a number-- (0 to change Bases): ');
Readln(NStr);
m := Length(Nstr);
OK := m > 0;
While (m > 0) and (OK) do
Begin
(* For BaseIn > 42, 'a' = 42, otherwise convert lower to upper case *)
If BaseIn < 43 then NStr[m] := UpCase(NStr[m]);
Dval := SymVal(NStr[m]);
OK := (Dval < BaseIn) AND (Dval >= 0); (* err check *)
If OK then Dec(m)  (* parse chars from last to first *)
Else
Begin   (* do over *)
Write(bel);
DisplayRange(BaseIn);
End;
End;
Until OK;
End;

BEGIN   (* main program *)
(* Demo of largest integer allowed converted to base from 2 to 16 *)
(* Input is a LongInt, output is a String *)

Writeln; Writeln; Writeln;
Writeln('Largest value in this program is ', Big10, ' which
is:');
For BaseOut := 2 to 16 do
Writeln(IntToStr(Big10, BaseOut), ', base ', BaseOut);
Writeln;

Repeat  (* new bases or quit *)
Repeat  (* until new bases are proper *)
Write('Enter input and output bases from 2..72');
Write('--(0 0 to quit): ');
Readln(BaseIn, BaseOut);
BasesOK := (BaseIn in [0, 2..72]) and (BaseOut in [0, 2..72]);
If not BasesOK then Write(bel);
Until BasesOK;
If (BaseIn = 0) OR (BaseOut = 0) then EXIT;  (* program *)

DisplayRange(BaseIn);  (* tutoring prompt *)
Repeat   (* new number conversions with same bases *)
GetNumber(SymStrIn);
If SymStrIn <> '0' then
Begin
(* convert input string to an integer value *)
IntVal := StrToInt(SymStrIn, BaseIn);
If IntVal <= 0 then  (* it's wrong *)
Begin
Write(bel);
DisplayRange(BaseIn);
End
Else
Begin
(* convert value to an output string *)
SymStrOut := IntToStr(IntVal, BaseOut);
(* display results *)
Write(SymStrIn, ', base ', BaseIn, ' = ', IntVal);
If BaseOut <> 10 then
Write(' = ', SymStrOut, ', base ', BaseOut);
Writeln;  Writeln;
End;
End;
Until SymStrIn = '0' (* change bases or quit *);
Until BaseIn = 0;
END.

Mon, 30 Nov 1998 03:00:00 GMT

 Page 1 of 1 [ 1 post ]

Relevant Pages

Powered by phpBB® Forum Software