THE PUZZLET PAGE


How_Does_It_Work


FUNCTION:  Hex2Dec().  This useful function takes a hexadecimal word in string format its argument  and converts it into the denary form, returning this as an integer.

This code will only do conversions up to the maximum possible value of its return integer parameter. So, when declaring Hex2Dec(), its paramater must be declared as type int, uint, etc. See the table below for the limits.

Type

Exponent of 2
Value

int 230 1073741824
uint 231 2147483648
int64 261 2305843009213693952
uint64 262 4611686018427387904

Declaring the function must be done like this:

declare Hex2Dec(h: string)
Here's the code:

sub Hex2Dec(h$)
' Argument h$ must be a string-formatted
' hexadecimal number. Function converts
' it to denary and returns as integer.
def ascii, dec, L, p, temp: int
L = len(h$)
dec = 0: 'initialise denary value
for p = 1 to L: 'points to each character
    'convert character to ascii
    ascii = asc(mid$(h$, p, 1))
    select 1
        ' case 0 to 9
        case (ascii > 47 & ascii < 58)
            temp = ascii - 48
        ' case A to F
        case (ascii > 64 & ascii < 71)
            temp = ascii - 55
        default: 'error condition
            print "Error!"
            end
    endselect
    'convert character to denary & totalise
    dec = dec + temp*16^(L - p)
next p
return dec

Inset is a simple flowchart which describes the algorithm used. Each character is inspected one at a time.  If it's in the range zero to nine inclusive, no initial correction will be necessary.  If it's A, B, C, D, E, or F it will need to be corrected to value 10 to 15 respectively.

Next comes correction for position.  For example, in denary the leftmost digit of the number 37 really means "3 x 10 = 30."  Similarly, the leftmost digit in the hexadecimal number B5 really means "B x 16 = B0." Note that B0 in hex is 176 in denary! All the characters are dealt with in the same way until the whole conversion is complete.

flowchart

The following lines of code do all the work.  I've numbered them to make explanations simpler.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

L = len(h$)
dec = 0
for p = 1 to L
   ascii = asc(mid$(h$, p, 1))
  select 1
     case (ascii > 47 & ascii < 58)
        temp = ascii - 48
     case (ascii > 64 & ascii < 71)
        temp = ascii - 55
    default
        print "Error!"
        end
  endselect

  dec = dec + temp*16^(L - p)
next p
return dec

Let's look at the above code in detail now, using those line numbers.

1

L = len(h$). Variable L is inialised to hold the number of characters in variable h$.  For example, if h$ is "AFC" the L will be loaded with 3.

2

dec = 0. Variable dec will eventually hold the denary value of the function's argument, h$, so it's initialised here to zero.

3

for p = 1 to L. Opens the main for-next loop, using variable pp is an abbreviation for pointer.  It is used to point at each character in h$ one at a time.  The range is from the first character to L, which is just the length of h$, so that each and every character is inspected one at a time and in order.

4

ascii = asc(mid$(h$, p, 1)).  Line 4 addresses the problem of dealing with characters that can be ordinary digits ( o - 9) or alpha's (A - F).  It will encode it in a manner which will make it translatable to denary.  Let's look at the line from the inside.

mid$(h$, p, 1) Isolates the first character pointed to in by pointer p.
asc(mid$(h$, p, 1)) Takes the isolated character and converts it into ascii code.  So characters 0 - 9 and become  48 - 57, and characters A - F become 65 to 70.
ascii = asc(mid$(h$, p, 1)) Store the ascii-code in variable ascii.

5

select 1. The code will now deal with the value stored in variable ascii, using the select-case method.

6

case (ascii > 47 & ascii < 58).  We deal firstly with the case where variable ascii's stored value lies between 48 and 57, which occurs when we are dealing with a hexadecimal character from 0 to 9.  The required action is
spelt out in line 7.

7

temp = ascii - 48.  In the case that ascii holds a value in the range 48 - 57, we can convert it directly back to a decimal value, and this is accomplished by subtracting 58 from that value.  The result is stored in variable temp.

8

case (ascii > 64 & ascii < 71).  This is the second case, which occurs when dealing with the characters A to F. The action is shown in line 9.

9

temp = ascii - 55.  In this case, the code converts the values A through F into the decimal equivalent of 10 through 15 by subtracting 55 from the stored value in variable ascii and saving it in variable temp.

10

default. Normally the program will have found an acceptable case as above, and will skip directly from there to line 13.  However, line 10 provides a safety net.  If the calling routine has inadvertently passed an illegal character to function Hex2Dec, such as "Q" for instance, it will be caught as a default.  Appropriate action is dictated in line 11.  

11

print "Error!".  If the calling routine passes an illegal character to the function, this error message will be printed to the computer screen.

12

end.  There is no point continuing with the program if illegal characters are being fed to it, and the line 12 terminates it.

13

endselect.  Housekeeping: closes the select-endselect clause opened in line 5.

14

dec = dec + temp*16^(L - p).  The code now makes the correction for position shown in the flowchart above.  The formula shown here includes the correction and totalises the corrected figure in variable dec.

Here's an example, for, say, the hexadecimal word "C3," looking at the first character (C).  The value of L here will be 2, the length of the word.  The pointer p will be 1, pointing at the first character.

Variable temp will be 12, the value of C after passing through the ascii process.  Finally, dec will hold zero at this time.

So our formula now reads dec = 0 + 12 x 16(2-1) which evaluates correctly to 192.

15

next p.  Housekeeping: closes the for-next loop opened in line 3.

16

return dec.  The code has now finished the conversion, and the hexadecimal argument's value has been converted into denary and totalised into variable dec.  All that's necessary is to return this value to the calling routine.



MAIN MENU
HOW DOES IT WORK?

Site design/maintenance: Dave Ellis E-mail me!
Last Updated: February 4th, 2010.