|
|
Title | Convert values between decimal, hexadecimal, octal, and binary |
Keywords | convert, decimal, hexadecimal, octal, binary, base |
Categories | Algorithms |
|
|
Decimal, hexadecimal, and octal representations are straightforward. To read a string in these formats, use CLng. Hexadecimal strings should begin with &H and octal strings should begin with &O.
To convert a value into a decimal, hexadecimal, or octal string representation, use Format$, Hex$, and Oct$ respectively. For example, Oct$(256) returns the octal representation of the value 256 (which is "400").
Working with binary values is trickier, largely because the leftmost bit in a number determines its sign. For example, the value &H7FFFFFFF has leftmost bit 0 and its decimal value is 2147483647. Adding 1 to this gives &H80000000 in hexadecimal. That value has its leftmost bit 1 and its decimal value is -2147483648.
A cool trick for working with binary values (pointed out to me by Chris Wagg) is to look at the digits in the number's hexadecimal digits individually. Rather than trying to work with the number's leftmost bits, pull them off the number and consider them separately. Then concatenate the results of working with the digits separately.
For example, consider the value &H80000000. The leftmost hexadecimal digit is 8. It's not too hard to convert the hexadecimal value 8 into the binary value 1000. Similarly you can convert the 0s into 0000. Then you can concatenate thes results to get &H80000000 = &B10000000 00000000 00000000 00000000 (I add the &B for consistency, it's not part of VB).
Interesting Fact: Half of a byte is called a nibble. Honest, I'm not making this up! A byte has a left nibble and a right nibble. This technique considers numbers one nibble at a time.
You reverse this process when you want to convert a binary representation into a numeric value. Consider the binary digits in groups of 4. Convert each group into a hexadecimal digit and concatenate them. When you're done, you can use CLng to convert the hexadecimal value into a numeric value if you like.
Now to some code. Subroutine DisplayValue uses CLng or the BinaryToLong function to convert a string value from decimal, hexadecimal, octal, or binary into a Long variable. It then uses Format$, Hex$, Oct$, and LongToBinary to display the value in different formats.
|
|
' Display the value in the indicated control in
' the other controls.
Private Sub DisplayValue(ByVal source As TextBox)
Dim txt As String
Dim value As Long
' Don't recurse.
If m_IgnoreEvents Then Exit Sub
m_IgnoreEvents = True
' Get the value.
On Error Resume Next
Select Case source.Name
Case "txtDecimal"
value = CLng(source.Text)
Case "txtHexadecimal"
txt = UCase$(Trim$(source.Text))
If Left$(txt, 2) <> "&H" Then txt = "&H" & txt
value = CLng(txt)
Case "txtOctal"
txt = UCase$(Trim$(source.Text))
If Left$(txt, 2) <> "&O" Then txt = "&O" & txt
value = CLng(txt)
Case "txtBinary"
value = BinaryToLong(source.Text)
End Select
On Error GoTo 0
' Display the value in different formats.
If source.Name <> "txtDecimal" Then
txtDecimal.Text = Format$(value)
End If
If source.Name <> "txtHexadecimal" Then
txtHexadecimal.Text = "&H" & Hex$(value)
End If
If source.Name <> "txtOctal" Then
txtOctal.Text = "&O" & Oct$(value)
End If
If source.Name <> "txtBinary" Then
txtBinary.Text = LongToBinary(value)
End If
m_IgnoreEvents = False
End Sub
|
|
Function BinaryToLong reads the binary bits that make up each nibble in the value. For each nibble, it calculates the nibble's value. It uses Hex$ to concatenate the nibble values into a hexadecimal string and finally uses CLng to convert the result into a Long value.
|
|
' Convert this binary value into a Long.
Private Function BinaryToLong(ByVal binary_value As String) _
As Long
Dim hex_result As String
Dim nibble_num As Integer
Dim nibble_value As Integer
Dim factor As Integer
Dim bit As Integer
' Remove any leading &B if present.
' (Note: &B is not a standard prefix, it just
' makes some sense.)
binary_value = UCase$(Trim$(binary_value))
If Left$(binary_value, 2) = "&B" Then binary_value = _
Mid$(binary_value, 3)
' Strip out spaces in case the bytes are separated
' by spaces.
binary_value = Replace(binary_value, " ", "")
' Left pad with zeros so we have a full 32 bits.
binary_value = Right$(String(32, "0") & binary_value, _
32)
' Read the bits in nibbles from right to left.
' (A nibble is half a byte. No kidding!)
For nibble_num = 7 To 0 Step -1
' Convert this nibble into a hexadecimal string.
factor = 1
nibble_value = 0
' Read the nibble's bits from right to left.
For bit = 3 To 0 Step -1
If Mid$(binary_value, 1 + nibble_num * 4 + bit, _
1) = "1" Then
nibble_value = nibble_value + factor
End If
factor = factor * 2
Next bit
' Add the nibble's value to the left of the
' result hex string.
hex_result = Hex$(nibble_value) & hex_result
Next nibble_num
' Convert the result string into a long.
BinaryToLong = CLng("&H" & hex_result)
End Function
|
|
Function LongToBinary uses Hex$ to create a hexadecimal representation of a Long value. It then examines each hexadecimal digit and converts them into binary.
|
|
' Convert this Long value into a binary string.
Private Function LongToBinary(ByVal long_value As Long, _
Optional ByVal separate_bytes As Boolean = True) As _
String
Dim hex_string As String
Dim digit_num As Integer
Dim digit_value As Integer
Dim nibble_string As String
Dim result_string As String
Dim factor As Integer
Dim bit As Integer
' Convert into hex.
hex_string = Hex$(long_value)
' Zero-pad to a full 8 characters.
hex_string = Right$(String$(8, "0") & hex_string, 8)
' Read the hexadecimal digits
' one at a time from right to left.
For digit_num = 8 To 1 Step -1
' Convert this hexadecimal digit into a
' binary nibble.
digit_value = CLng("&H" & Mid$(hex_string, _
digit_num, 1))
' Convert the value into bits.
factor = 1
nibble_string = ""
For bit = 3 To 0 Step -1
If digit_value And factor Then
nibble_string = "1" & nibble_string
Else
nibble_string = "0" & nibble_string
End If
factor = factor * 2
Next bit
' Add the nibble's string to the left of the
' result string.
result_string = nibble_string & result_string
Next digit_num
' Add spaces between bytes if desired.
If separate_bytes Then
result_string = _
Mid$(result_string, 1, 8) & " " & _
Mid$(result_string, 9, 8) & " " & _
Mid$(result_string, 17, 8) & " " & _
Mid$(result_string, 25, 8)
End If
' Return the result.
LongToBinary = result_string
End Function
|
|
For information on other algorithms, see my book Ready-to-Run Visual Algorithms.
|
|
|
|
|
|