Tutorial on number conversion, any base
Author Message Tutorial on number conversion, any base

Having seen many postings that request algorithms and programs to
convert decimal to binary, octal or hex and vice versa, here is a
back to basics approach that should allow anyone to convert ANY
base to ANY other base. Part of the confusion results from the
computer showing number values and number symbols just the same.

When you enter the symbols '123', unless forced, you do not
think:

The value of '123' is (1 * 10^2) + (2 * 10^1) + (3 * 10^0).

However, that is the way ALL single base number systems work.
(Roman numerals are not single based and relate to abacus like
calculation.) Base to the 0 power always has a value of 1 and is
always in the rightmost position. Each symbol position to the
left has a position value of the base times the position value
to its right. Since the rightmost is always 1, it is easy to
progress to the left and find all the position values.
In binary (base 2) this becomes:
..... 2^4   2^3   2^2   2^1   2^0
position value--  16    8     4     2     1
In hex (base 16) this becomes:
..... 16^4  16^3  16^2  16^1  16^0
position value--65636  4096   256   16     1
or in general:
..... Base^3  Base^2  Base^1  Base^0
position value    --      --      Base      1

A feature that can be used for error checking is that no digit
symbol can have a value equal to or greater than the base. For
EVERY base the symbol string representing the base value is '10'.

For bases 10 or less we could use something like the VAL command
of Turbo and QBasic, however, in hex the symbols above '9' would
not work. By convention, we use alphabetic characters as numeric
symbols when the base exceeds 10. That can be done even for bases
greater than 16 if you choose. Given that A = 10, B = 11..F = 15,
that completes what you need to convert numerical symbol
strings representing ANY base, 2..16, to their integer values.
Here is a program fragment:

VAR
SymbolStringIn:String;    (* alpha-numeric string to convert *)
n, BaseIn:Integer;
PosValue, IntVal:LongInt;
NumSymbol:Char;
...............

Begin
n := Length(SymbolStringIn);  (* "While" loop counter *)
IntVal := 0;     (* becomes the value of SymbolStringIn *)
PosValue := 1;   (* the base^power value *)
While n > 0 do
Begin
NumSymbol := NumStrIn[n];  (* extract rightmost char *)
IntVal := IntVal + (SymVal(NumSymbol) * PosValue);
Dec(n);   (* move left one char *)
If n > 0 then PosValue := PosValue * BaseIn;
End;
End.

The programmer supplied Function SymVal (not shown) returns the
digit char value, i.e. 0 for '0', 2 for '2', 10 for 'A', 12 for
'C' and so on. The last "If n > 0" conditional keeps PosValue as
low as possible in an attempt to avoid out of range numbers for
the computer. You still need other safeguards if you intend to
use numbers which approach the maximum value of LongInt.

Going from an integer to a new base still uses the same
knowledge-- we just go backwards. First, let's review how you
parse an integer into its separate digits with the integer 345:

(1) Rightmost digit is    345 Mod 10  giving 5
(2) Stripping the 5 away to leave the rest is done by:
345 Div 10  giving 34
Repeat (1) and (2) until done.

ANY base works the same, just put the value of the new base where
10 is above. However, to display the answer, you convert each
digit to a symbol representing that digit's value.

VAR
SymStringOut:String;
IntVal:LongInt;
BaseOut, DigitVal:Integer;
Ch:Char;
.............

Begin
SymStringOut := '';
While IntVal > 0 Do  (* value still to be converted *)
DigitVal := IntVal Mod BaseOut;  (* rightmost digit *)
Ch := DigitSymbol(DigitVal);
NumStringOut := Concat(Ch, NumStringOut);
IntVal := IntVal Div BaseOut; (* remove previous digit *)
End;
End.

The programmer supplied Function DigitSymbol (not shown) returns
the symbol corresponding to the DigitVal.

With these facts you can convert any base to any other base by
first converting the input symbol string (base in) to an integer
value and convert that value to the output symbol string (base
out). By setting the input and output bases equal, you can
perform arithmetic on the value and make it look like you are
doing addition in binary, subtraction in hex, etc.

Under separate posting is a conversion program of wider utility
than most will ever need covering bases from 2 to 72. In addition
to the basics above it adds range checking to avoid over range
errors.

If you use a really old version of Pascal that does not include
the dynamic TYPE STRING, changes must be made. You can represent
the symbol strings as TYPE "Array [0..32] of Char" and use the
zero'th element to store the length as Chr(length). The length is
extracted with ord( ). No delete, insert or copy is used BUT, as
shown above, concantenation is. One way to do concantenation
with the added char going to the front of the string (as done
above) is to put the chars in from array element 1 on up and keep
the length byte up to date. This stores the chars in reverse
order but, since you know the length, it is easy to write the
output string correctly by writing the char array in reverse:
For n := Ord(A) downto 1 do Write(A[n]);
Writeln;

Hope you found this useful,

Mon, 30 Nov 1998 03:00:00 GMT  Tutorial on number conversion, any base

Quote:
>Having seen many postings that request algorithms and programs to
>convert decimal to binary, octal or hex and vice versa, here is a
>... ... ...

>Hope you found this useful,

Please find out how you can cross-post - this is the second COPY of the
message that I've received, because you have, it seems, posted twice.

--