How To Transform (Convert) Numbers Between Decimal, Binary, Hex, and Octal-VBForums

# Thread: How To Transform (Convert) Numbers Between Decimal, Binary, Hex, and Octal

1. ## How To Transform (Convert) Numbers Between Decimal, Binary, Hex, and Octal

In order to determine how to transform numbers between decimal, binary, hex and octal (numbers in base 10, 2, 16 and 8) you must first learn how to count in other bases including binary. Counting in binary is almost identical to counting in decimal, the only difference is that the highest digit allowed is 1 instead of 9, meaning it only consists of the lowest digit 0 and the highest digit 1. The rest is the same, simply add one by adding one to the far right column.

Binary - Decimal
0000 = 0; to add one in binary just add 1 to the far right hand column just like decimals so 0000 + 0001 = 0001.
0001 = 1; as 1 is the highest digit allowed in base 2 you can't add 1 and make it 0002, instead it is exactly the same as getting to the highest digit in base 10 which is 9, meaning that in binary 0001 + 0001 = 0010.
0010 = 2, and so on.
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = 8

Now that you can count in binary, observe that:
Binary - Decimal
0001 = 1 (1 x 2^0 = 1) Please note that any number to the power of 0 = 1 e.g. 8^0 = 1.
0010 = 2 (1 x 2^1 = 2) Please also note that any number to the power of 1 = number e.g. 8^1 = 8.
0100 = 4 (1 x 2^2 = 4)
1000 = 8 (1 x 2^3 = 8)
Which are all powers of 2, meaning each column represents a power of 2 in the same way that each column in decimal represents a power of 10.

This means that the decimal value of any binary number can be determined simply by adding the value of the bits that are set:
If the first bit is set ie 0001 then the decimal value is + 1*2^0 (+ 1)
If the second bit is set ie 0010 then the decimal value is + 1*2^1 (+ 2)
If the third bit is set ie 0100 then the decimal value is + 1*2^2 (+ 4)
If the 4th bit is set ie 1000 then the decimal value is + 1*2^3 (+ 8)
Note that any bits that are not set have the value of zero as 0 x 2^any number = 0 e.g. 0 x 2^3 -=0.

So to convert from binary to decimal is now easy, simply add the value of each bit:
1111(binary) = 1 x 2^0 + 1 x 2^1 + 1 x 2^2 + 1 x 2^3 = 1 + 2 + 4 + 8 = 15

What is the value of the binary number 0101 as a decimal?
0101(binary) = 1 x 2^0 + 0 x 2^1 + 1 x 2^2 + 0 x 2^3 = 1 + 0 + 4 + 0 = 5(decimal)

Now you tell me: what is the binary number 1010 as a decimal?
If you can answer, good job, you have learned how to count in binary and then convert from binary to decimal.

-------------------------------------------------------------------------------

Now you have made the breakthrough you can move on to count in hex. Hex is base 16. How do I count in base 16 when the digits used to represent base 10 numbers run out at 9 [0-9]?

The answer is that letters are used to represent numbers greater than 9. Specifically:
10 = A
11 = B
12 = C
13 = D
14 = E
15 = F
Which can be summarised as Hex: base 16 [0-9][A-F].

Counting in Hex is just as easy as in decimal or binary, the only difference is that the highest hexadecimal digit allowed is represented by the letter F.
hex - decimal
0001 - 1
0002 - 2
0003 - 3
0004 - 4
0005 - 5
0006 - 6
0007 - 7
0008 - 8
0009 - 9
000A - 10
000B - 11
000C- 12
000D - 13
000E - 14
000F - 15 <- highest hex digit allowed in base 16 is F, therefore 000F + 0001 = 0010
0010 - 16
0011 - 17
0012 - 18
....
00FF - 255
0100 - 256
....
0FFF - 4095
1000 - 4096

To convert from hex to decimal is very similar to converting from binary except the base (also called radix) is 16 not 2.

Observe that:
hex - decimal
0001 = 1 x 16^0 = 1
0010 = 1 x 16^1 = 16
0100 = 1 x 16^2 = 256
1000 = 1 x 16^3 = 4096
Meaning each column represents a power of 16.

So now it is possible to transform hex to decimal with relative ease:
1111(hex)= 1 x 16^0 + 1 x 16^1 + 1 x 16^2 + 1 x 16^3 = 1 + 16 + 256 + 4096 = 4369(decimal)

Slightly harder but not much, remember A = 10, B = 11, C = 12, D = 13
DCAC(hex) = 12 x 16^0 + 10 x 16^1 + 12 x 16^2 + 13 x 16^3 = 12 + 160 + 3072 + 53248 = 56492(decimal)

What is the decimal value of A8B7?
If you can answer, good job, now you can convert between hex and decimal.

One last thing to note regarding hex, the shorthand for hex can be the prefix 0x- which can be confusing as 0x18 actually means 18(hex) = 8 x 16^0 + 1 x 16^1 = 24(decimal) not 0; the key is noticing that there are no spaces indicating that 0x18 is a single number not an operation on a number.

-------------------------------------------------------------------------------

Now that you can count in binary and hex and convert them to decimal, it will be easy to do octal as there are no letters involved. Octal: Base 8 [0-7].

Octal - decimal
0000 - 0
0001 - 1 x 8^0 = 1
0002 - 2
0003 - 3
0004 - 4
0005 - 5
0006 - 6
0007 - 7 <- the highest digit allowed in base 8 so to add 1 to 0007(octal) must be 0010
0010 - 1 x 8^1 = 8
...
0100 - 1 x 8^2= 64
...
1000 - 1 x 8^3 = 512

1111(octal) = 1 x 8^0 + 1 x 8^1 + 1 x 8^2 + 1 x 8^3 = 512 + 64 + 8 + 1 = 585(decimal)

What is 5678(octal) in decimal?
If you can answer, good job, now you can convert between octal and decimal.

2. ## Re: How To Transform (Convert) Numbers Between Decimal, Binary, Hex, and Octal

Good write up! Although, you brought back terrifying memories of when I learnt this stuff at school.

3. ## Re: How To Transform (Convert) Numbers Between Decimal, Binary, Hex, and Octal

No worries Nightwalker83, and hopefully this summary was easier to understand and not as terrifying.

4. ## How to write functions to transform a number from decimal to binary

Next - How to write functions to transform a number from decimal to binary.

The easiest way to transform a decimal number into binary is to use the AND operator to check if each bit is set. So if you wanted to check if the first 4 bits are set in a decimal number you would have to code:
Code:
```
if (number And 2^0) then bit 1 set
if (number And 2^1) then bit 2 set
if (number And 2^2) then bit 3 set
if (number And 2^3) then bit 4 set```
Now it should be easy to write a decimal to binary function by systematically checking each bit using the same method. For example:
vb Code:
`Function DecToBin1(ByVal X As Long) As StringDim BitChecker As LongDim Counter As Long Do    BitChecker = 2 ^ Counter 'bit to check which increases to the next bit every Loop        If (BitChecker And X) Then ' check If a bit is Set        DecToBin1 = "1" & DecToBin1 ' If yes add a 1    Else        DecToBin1 = "0" & DecToBin1 ' otherwise add a 0    End If        Counter = Counter + 1 Loop Until 2 ^ Counter > X ' stop once 2 ^ Counter (the BitChecker) is bigger than the number being checked. End Function`
Once you understand the DecToBin1 function, you can then move on to examining how this next version works:
vb Code:
`Function DecToBin2(ByVal X As Variant) As String Do    DecToBin2 = (X And 1) & DecToBin2 ' check the bit    X = Fix(X / 2) ' dividing by 2 is the same as dividing by 10 in decimal i.e. it moves the decimal one place to the left, and then use fix to get rid of any remainder. Loop While X > 0End Function`
This is slightly different as it checks each bit starting with the decimal value of the number and then dividing the number being checked by 2 each iteration. The key to understanding this function is that dividing by 2 in binary is the same as dividing by 10 in decimal - it moves the decimal one place to the left.

So the function does this if the number being transformed is 16 (10000 in binary):
16 (10000) and 1 = 0 (Least significant bit - rightmost bit)
8 (1000) and 1 = 0
4 (100) and 1 = 0
2 (10) and 1 = 0
1 (1) and 1 = 1 (Most significant bit - far left bit)

Next on to the extension as the previous function DecToBin2 hits a limit of 2,147,483,647 (2^31) in relation to bitwise comparisons. Thus DecToBin2(2147483647) will work, where as DecToBin2(ToBin(2147483647 + 1) will fail even if you use decimal data types in the function.

This next function, DecToBin3, can overcome the limitation of the bitwise comparison:
vb Code:
`Function DecToBin3(ByVal X As Variant) As String 'Witis X = CDec(X) ' change the number into a variant to cope with large numbers Do    DecToBin3 = (Fix(X / 2) * 2 = Fix(X)) + 1 & DecToBin3 ' check the bit    X = Fix(X / 2) ' dividing by 2 is the same as dividing by 10 in decimal i.e. it moves the decimal one place to the left, and then use fix to get rid of any remainder. Loop While X > 0End Function`
The key to understanding this function is that the bit is checked slightly differently. If the binary representation of a number ends in zero, then there will be no remainder if the decimal place is moved one place to the left, otherwise if there is a remainder the bit must have been set. Checking the bits this way allows integers containing up to 28 digits to be transformed from decimal to binary. E.g.
Code:
```Private Sub Command1_Click()
Dim s\$
s = String(28, "9")
Debug.Print DecToBin3(s)
End Sub```
If you understand the DecToBin1, DecToBin2 and DecToBin3 functions, good job, you have now figured out how to cut some code to transform numbers from decimal to binary.

5. ## Re: How To Transform (Convert) Numbers Between Decimal, Binary, Hex, and Octal

Maybe you should address high bit with Integer & Long values, how to prevent overflow when converting. As is, your functions won't work with negative values

6. ## Re: How To Transform (Convert) Numbers Between Decimal, Binary, Hex, and Octal

Originally Posted by LaVolpe
As is, your functions won't work with negative values
You are absolutely correct LaVolpe, I'll have to extend it to cope with negative values.

7. ## Negative Values

Next - how to implement negative values in binary.

Although it would be acceptable to simply add a negative sign to the far left of any binary number to indicate a negative, this is not how information is stored and used in binary systems, so the sign itself must also be transformed into binary. The easiest way to create negative numbers in binary is to use the most significant bit (the leftmost bit) to act as the sign, where 0 indicates a positive value and 1 indicates a negative value, which is just like putting a negative sign ahead of the number.

However as one of the bits is used for the sign, it effects the range of values that can be held. For example a byte is eight bits 0000 0000 and if it is unsigned it can hold values between 0-255 (1111 1111(binary) = 255(decimal)). However, if the far left bit is used for the sign, it means there are only 7 binary digits to hold the value of number being expressed meaning the range is then -127 to +127 where 0111 1111 = + 127 and 1111 1111 = - 127. The key is remembering that the most significant bit is on for negative numbers and that's all there is to it.

Here is a function that implements the sign and magnitude method just described:
vb Code:
`Function DecToBin4(ByVal X, ByVal NumBits&) As String ' Sign Method for Negative Numbers 'Witis If X < 0 Then DecToBin4 = "-" ' to indicate a negative number X = Abs(CDec(X)) ' change the number into a decimal type to cope with large numbers Do    DecToBin4 = (Fix(X / 2) * 2 = Fix(X)) + 1 & DecToBin4 ' check the bit    X = Fix(X / 2) ' dividing by 2 is the same as dividing by 10 in decimal i.e. it moves the decimal one place to the left, and then use fix to get rid of any remainder. Loop While X > 0 DecToBin4 = String(NumBits - Len(DecToBin4), "0") & DecToBin4 ' as the format function fails with large strings If Right(DecToBin4, 1) = "-" Then DecToBin4 = "1" & Left\$(DecToBin4, Len(DecToBin4) - 1) ' do the negative numbersEnd Function`

This function can transform even large negative numbers into binary e.g.:
Code:
```Private Sub Command1_Click()
Dim n
n = String(28, "8")
Debug.Print DecToBin4(n, 96) ' large postive number
Debug.Print DecToBin4("-" & n, 96) ' large negative number
End Sub```
In addition there are several alternative methods of implementing negative numbers in binary, the most widespread being two's complement. Two's complement is somewhat counterintuitive and very unreadable, nonetheless, here is how to implement it:
Take a postive binary number and invert all the bits then add 1
Code:
```        0000 0001 (+1 binary)
1111 1110  step 1 invert the bits
1111 1111  step 2 add 1 (-1 binary in two's complement)```
And here is a function which implements two's complement for large negative numbers, which by the way is implemented by the windows calculator, try it yourself - just set the view to programmer.
Code:
```Function DecToBin5(ByVal X, ByVal NumBits&) As String ' Two's Complement Method for Negative Numbers
Dim Neg As Boolean: If X < 0 Then Neg = True ' for negative numbers
X = Abs(CDec(X)) ' change the number into a decimal type to cope with large numbers
Do
DecToBin5 = (Fix(X / 2) * 2 = Fix(X)) * IIf(Neg, -1, 1) + IIf(Neg, 0, 1) & DecToBin5 ' checks the bit (and inverts the bit for negative numbers)
X = Fix(X / 2) ' dividing by 2 is the same as dividing by 10 in decimal i.e. it moves the decimal one place to the left, and then use fix to get rid of any remainder.
Loop While X > 0
DecToBin5 = String(NumBits - Len(DecToBin5), IIf(Neg, "1", "0")) & DecToBin5 ' as the format function fails with large strings
If Neg Then DecToBin5 = Left\$(DecToBin5, InStrRev(DecToBin5, "0") - 1) & "1" & String(Len(DecToBin5) - InStrRev(DecToBin5, "0"), "0") ' then add one to negative numbers.
End Function```
If you can understand the DecToBin4 and DecToBin5 functions, good job, you can now transform negative values into binary.

8. ## Back to Decimal

Next is how to transform binary numbers back into decimals.

The easiest way I can think of which won't break with large numbers is to change the binary string into a series of bytes and examine each byte to see it is set, and if it is multiply by the value of the column it represents, i.e. simply add the value of the bits that are set.

Here is an example which does exactly this and also makes use of the decimal variable type to allow transformation of large binary strings:
Code:
```Function BinToDec(ByVal sBin As String) As Variant
Dim ba() As Byte, i&, bitval As Variant
bitval = 1
ba = StrConv(sBin, vbFromUnicode) ' transform the string into a byte array
For i = UBound(ba) To 0 Step -1
If ba(i) = 49 Then BinToDec = CDec(BinToDec + bitval) ' chr(49) = 1, so I am merely checking if the bit is set and then adding the bitvalue which is determined by which column the bit is from.
bitval = CDec(bitval * 2) ' increase the bitval by multiplying by 2 to reflect the value of the next column
End Function```
The key to understanding this function is realising that multiplying the bitvalue by 2 each iteration allows it to grow as a power of 2 e.g. it starts as 1 (1 x 2^0), 2 (1 x 2^1), 4 (1 x 2^2), 8 (1 x 2^3) etc.

Note that it can even transform a string containing 95 bits into a decimal value:
Code:
```Private Sub Command1_Click()
Dim s\$
s = String(95, "1")
Debug.Print BinToDec(s)
End Sub```
If you can understand the function, good job, you can now transform positive integers from binary back into decimal.

9. ## Decimal to any radix and back again

Next is how to write functions to transform decimal numbers to any radix (base) 2-62 and then back again.

It is now relatively easy to extend all of the previously explicated functions to allow transformation to and from any base 2-62 (where base 62 [0-9][A-Z][a-z]) which can also handle large numbers via the decimal datatype. The next function transforms a decimal number into any radix 2-62:
vb Code:
`Function DecTo(ByVal x, ByVal Radix&) As String ' Witis transforms up to 27 digit positive integer from decimal to any base 2-62 If (Radix < 2) Or (Radix > 62) Then Exit Function Dim y&: x = CDec(x) Do    y = (x / Radix - Fix(x / Radix)) * Radix ' get dec value of the rightmost column given the radix    If y < 10 Then        DecTo = y & DecTo ' add a numerical digit    ElseIf y < 36 Then DecTo = Chr\$(y + 55) & DecTo ' non num digit [A-Z]    ElseIf y < 62 Then DecTo = Chr\$(y + 61) & DecTo ' non num digit [a-z]    End If    x = Fix(x / Radix) ' move the point to the left one place and discard the remainder Loop While xEnd Function`
This function determines the decimal value of the rightmost column given the radix and then converts it into the alpha numeric code [0-9][A-Z][a-z], then moves the point one place to the left until the entire number is transformed from decimal to the chosen radix.

For example 55 decimal to Hex which is (3A):
The first iteration works out that the rightmost column contains 0.625 of the radix or 10 which is represented by the letter A in hex.
The next iteration determines that the rightmost column contains 0.1875 of the radix or 3 which is also represented by 3 in hex.

The next function allows numbers from other radixes 2-62 to be transformed back into decimal:
Code:
```Function ToDec(ByVal x, ByVal Radix&) As Variant
' Witis transforms any postive whole number from any base 2-62 to a decimal value
If (Radix < 2) Or (Radix > 62) Then Exit Function
Dim ba() As Byte, i&, bitval As Variant, b As Byte
bitval = 1
ba = StrConv(x, vbFromUnicode)
For i = UBound(ba) To 0 Step -1
b = ba(i)
If b < 58 Then
ToDec = CDec(ToDec + (b - 48) * bitval)
ElseIf b < 91 Then ToDec = CDec(ToDec + (b - 55) * bitval)
ElseIf b < 123 Then ToDec = CDec(ToDec + (b - 61) * bitval)
End If
bitval = CDec(bitval * Radix)
Next i
End Function```
This function checks each bit from right to left and works out it's numerical value in decimal, for example A in hex is 10 decimal. Then it simply multiplies this number by the bit value.

For example:
2A in hex
A = 10 decimal * bitvalue = 10 * 16^0 = 10
2 = 2 decimal * bitvalue = 2 * 16^1 = 32
so the answer 2A hex = 42 decimal

67 Octet
7 = 7 * 8^0 = 7
6 = 6 * 8^1 = 48
so the answer is 55 decimal

Example usage to convert a 27 digit integer to every base 2-62 and back again; output is to the debug window (ctrl+g):
Code:
```Private Sub Command1_Click()
Dim res, lbase&, i&
For i = 2 To 62 Step 1
lbase = i
res = DecTo("888888888888888888888888888", lbase)
Debug.Print res
res = ToDec(res, lbase)
Debug.Print res
Next i
End Sub```
If you can understand these functions, good job, you can now transform positive integers from decimal to any radix and back again including binary, hex and octal.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

Featured

Click Here to Expand Forum to Full Width