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[32];   (* 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  
 
 [ 1 post ] 

 Relevant Pages 

1. Program for number conversion, bases 2..72

2. Base 10/Base 2 or Base 2/Base 10 conversion

3. base conversion of large numbers

4. base conversion of large numbers

5. Tutorial on number conversion, any base

6. Tutorial on number conversion, any base

7. Solution: fast diskcopy in BP7.0 in 72 sec

8. base conversion

9. Numbers Conversion

10. number conversion in pascal

11. Conversion from numbers to words

12. Number conversions

 

 
Powered by phpBB® Forum Software