The Wonderful Hex

If you've read the binary article, you might already know quite a bit about hex. Anyways, hexadecimal numbers are based to 16 numbers unlike the normal decimal system, which bases on 10 numbers. But why hexadecimals exist? To put it simply, they are easier to use and understand in programming than decimals.

Here is a quick table to get started with:

Code:
0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
At this point, I have to say one major note about hexadecimals: for computer, it is all the same how numbers are displayed to you or the user. It processes the numbers in binary, but for humans decimals and hexadecimals tell a whole lot more and this is the reason these formats are used. So however you view the numbers, only thing that matters for computer are the binary numbers.

One of the most common thing about hex numbers is how to convert values into displayable hex strings and vice versa. I did write something related to this in the binary article, but I tell the basics here as well, along with some additional information.

First major problem is with strings. You could use Chr$() or ChrW$() to add the resulting characters into a string and Asc or AscW together with Mid$() to get the character codes, but this is slow.

The next problem are the character codes. After taking a look at character map, you might notice one interesting thing:

Code:
Code	Hex	Binary	Character
48	30	00110000	0
49	31	00110001	1
50	32	00110010	2
51	33	00110011	3
52	34	00110100	4
53	35	00110101	5
54	36	00110110	6
55	37	00110111	7
56	38	00111000	8
57	39	00111001	9
58	3A	00111010	:
59	3B	00111011	;
60	3C	00111100	<
61	3D	00111101	=
62	3E	00111110	>
63	3F	00111111	?
64	40	01000000	@
65	41	01000001	A
66	42	01000010	B
67	43	01000011	C
68	44	01000100	D
69	45	01000101	E
70	46	01000110	F
Character code &H30. See what it is in binary? 00110000 - why this is interesting? Well, the four lower bits are unactive. And the four lowest bits are just enough to fill them with hexadecimal information, because binary 1111 is 15, which is the biggest hexadecimal number.

This doesn't resolve one thing though: how do we get "ABCDEF" instead of characters ":;<=>?" ? If you put any thought into it, you soon realise an easy solution for this.

In any case, always when we want to prevent slow code (= string processing), we have to take a look into alternative methods. Fastest you could get are Long arrays, because 32-bit values are native to a modern processor. Well... we have 64-bit processors pushing through to the consumer market, but they have a very good 32-bit support. The problem is converting these arrays to strings and you need to use API to do this (CopyMemory aka RtlMoveMemory to be exact). So we'll have to say no to this, as I personally prefer pure VB code (you can take a look in the VBspeed article though if you want to learn the very fastest methods you can get with VB). So, the second best choise is to use byte arrays, because you can directly convert these into strings with pure VB code.

One thing we need to notice with strings is that they're unicode. Two bytes per character. Thus the byte array must be two times the number of characters. Another thing related to the byte arrays is that the base index is 0. So instead of just placing the exact number of characters times two, you should decrease the value by one.

Now it is the time for some code examples, so I can be more clear on what I mean. The code below should be very easy to follow, as it does byte to hex string conversion.

VB Code:
  1. 'in a module (functions are fastest to call from a module)
  2. Public Function ByteToHexStr(ByVal Value As Byte) As String
  3.     'buffer to hold 2 characters (2 * 2 - 1) and variable A for loops
  4.     Dim Buffer(3) As Byte, A As Long
  5.     'these hold the ripped numbers
  6.     'as said before, longs are a bit faster to handle than bytes
  7.     Dim HighByte As Long, LowByte As Long
  8.     'first of all, rip the high bits and make them low bits
  9.     HighByte = (Value And &HF0) \ &H10
  10.     'then get the lower four bits
  11.     LowByte = Value And &HF
  12.     'check if the code is below the letters ABCDEF
  13.     If HighByte < &HA Then
  14.         'now add the character code for zero
  15.         HighByte = HighByte Or &H30
  16.     Else 'A, B, C, D, E or F
  17.         'at minimum, we get number 10 here, character code for A is 65, thus we add 55
  18.         HighByte = HighByte + 55
  19.     End If
  20.     'now the same as above for the lower four bits
  21.     If LowByte < &HA Then
  22.         LowByte = LowByte Or &H30
  23.     Else
  24.         LowByte = LowByte + 55
  25.     End If
  26.     'now assign these to the byte array
  27.     Buffer(0) = HighByte
  28.     Buffer(2) = LowByte
  29.     'and then convert to a string and return it
  30.    ByteToHexStr = Buffer
  31. End Function


Then you probably like to do a quick test. Thus:

VB Code:
  1. 'in a form
  2. Private Sub Form_Load()
  3.     Dim TestValue As Byte
  4.     TestValue = 255
  5.     MsgBox "Number '" & TestValue & "' in hex is '" & ByteToHexStr(TestValue) & "'"
  6.     Unload Me
  7. End Sub


Now that we have done it this way, how about the other way around? Maybe this can be a matter for yourself to figure out, now that you saw quite a tip with the code above. Also, you have a challenge doing the same function for Integer and Long values, because they're signed data types, whereas byte is unsigned (= can't be negative). In the other hand, I do provide more advanced functions to play with elsewhere on the site.

Anyways, I hope this all clear up the mess considering hexadecimal values in your mind and you learned something from this

One last note in the end: the code sample above is fast once you compile the program.

---

There. All (constructive) feedback is welcome