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.
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.
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.
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 String
Dim BitChecker As Long
Dim 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 > 0
End 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 > 0
End 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.
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
Re: How To Transform (Convert) Numbers Between Decimal, Binary, Hex, and Octal
Quote:
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.
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 x
End 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
What about Octet?
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.