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,

Wed, 18 Jun 1902 08:00:00 GMT  Tutorial on number conversion, any base

Quote:

>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.

Here is a shorter program fragment; untested, but I'm sure it's about
right :

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

Begin
IntVal := 0 ;     (* becomes the value of NumStrIn *)
for n := 1 to Length(NumStrIn) do begin
NumSymbol := NumStrIn[n] ;
IntVal := IntVal*BaseIn + SymVal(NumSymbol) ;
(* IntVal := IntVal*BaseIn + SymVal(NumStrIn[n]) *)
End ;

Of course, one should consider error checks.
--

Home Page under construction.

Wed, 18 Jun 1902 08:00:00 GMT  Tutorial on number conversion, any base

Quote:

>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.

Easiest way to covert a hex number to decimal is to add '\$' in front of
it and use val.

Osmo

Wed, 18 Jun 1902 08:00:00 GMT  Tutorial on number conversion, any base

:Easiest way to covert a hex number to decimal is to add '\$' in front of
:it and use val.

But the snag is that you'll need to recompile each time??

There is some additional information for the users on the
conversions in our standard

99848 May 19 1996 ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip
tsfaqp.zip Common Turbo Pascal Questions and Timo's answers

All the best, Timo

.....................................................................

Moderating at ftp:// & http://garbo.uwasa.fi archives  193.166.120.5
Department of Accounting and Business Finance  ; University of Vaasa

Wed, 18 Jun 1902 08:00:00 GMT  Tutorial on number conversion, any base

Quote:

>:Easiest way to covert a hex number to decimal is to add '\$' in front of
>:it and use val.
>But the snag is that you'll need to recompile each time??
>There is some additional information for the users on the
>conversions in our standard
> 99848 May 19 1996 ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip
> tsfaqp.zip Common Turbo Pascal Questions and Timo's answers

Also, Timo, there's a lengthy discussion in part 7 of my tutorial,
about how to go about number base conversions from base 10 to
something else and from something else to base 10.  There even
is a problem listed in there which is a number conversion from anybase
to anybase....I'm sure you might want to add this to your help list
you just made above...

ftp://garbo.uwasa.fi/pc/turbopas/tptutr11.zip

Wed, 18 Jun 1902 08:00:00 GMT  Tutorial on number conversion, any base

Quote:

>:Easiest way to covert a hex number to decimal is to add '\$' in front of
>:it and use val.

>But the snag is that you'll need to recompile each time??

How so? At least my copy of Turbo Pascal accepts variables as input to
val. The following program outputs 33.

var s:string;
x:word;
err:integer;

Begin
s:='\$21';
val(s,x,err);
writeln(x);
End.

Naturally the string \$21 could have been gotten from any source.

If you read values, you do not even need val if they are
already prefixed with \$, so any TP program that wants words can
accept hex numbers preceded by dollar signs. (Well that is unless the
programmer has done something stupid like checking is the characters
entered are actually numbers)

Osmo

Wed, 18 Jun 1902 08:00:00 GMT

 Page 1 of 1 [ 6 post ]

Relevant Pages

Powered by phpBB® Forum Software