将十六进制字符串转换为整数

时间:2014-09-10 20:42:18

标签: vb.net hex decimal valueconverter parity

Visual Basic 2010:最近在我的一个项目中,我的任务是以十六进制读取几个数据字段。每个字段长三个字符。所以这就是我一直在做的事情:

'Read the hex value and convert it to decimal
Dim hexVal as string  = "38D"
Dim intVal as integer = Convert.ToInt32(hexVal, 16)

'The integer result gets multiplied by a scaling factor
'(this is set by the manufacturer for each field).
Dim fac as single  = 200
Dim final as single  = intVal * fac
Debug.Print (final)

除了在这种情况下,这一直很有效:hexVal =“FFD”和fac = 32 .NET给我intVal = 4093,最终= 130976。 然而,我正在检查的遗留系统给出了-96。

我有点困惑,但理论上它是十六进制表示法。我对原始数据的唯一文档说明:字符按ISO字母5号编码,每个字符使用7位,即没有添加奇偶校验位。三个这样的字符将包含每个32位字的字段。

我是否错误地转换了这个?

附录:我已经研究了这些领域的定义,并发现几乎所有领域都是积极的(或未签名的)。少数可以是消极的或积极的(签名的)。查看遗留代码,对于每个十六进制字段,它们计算无符号结果和签名结果。如果预期该字段始终为正,则它们使用无符号结果。现在,如果该字段预期为负数或正数,则它们采用无符号结果,如果高于上限,则使用签名结果,否则使用无符号结果。以下是我到目前为止使用下面的片段:

    Dim hexVal As String, res As Single, decCeiling As Single
    Dim paddedHex1 As String, intVal1 As Integer = 0, resVal1 As Single = 0
    Dim paddedHex2 As String, intVal2 As Integer = 0, resVal2 As Single = 0
    Dim IsUnsignedInput As Boolean

    hexVal = "FB1"   'Raw hex input (in this case represents temperature in deg C)
    res = 0.125      'A resolution factor. Used to scale the decimal to a real-world nummber
    decCeiling = 150 'The maximum temperature we can expect is 150 degree Celcius
    IsUnsignedInput = False 'Is field unsigned or signed (for temps we can expect negative and positive)
    If hexVal.Length > 8 Then
        Throw New Exception("Input '" & hexVal & "' exceeds the max length of a raw input. The max is 8 characters.")
    EndIf

    'This calcualtion assumes an unsigned value (that is, always a positive number)
    paddedHex1 = hexVal.ToString.PadLeft(8, CChar("0"))
    intVal1 = Convert.ToInt32(paddedHex1, 16)
    resVal1 = intVal1 * res

    'This assumes a signed value (that is, could be a negative OR positive number.
    'Use two's complement to arrive at the result.
    paddedHex2 = hexVal.PadLeft(8, CChar("F"))
    Dim sb As New StringBuilder(paddedHex2.Length)
    For i As Integer = 0 To paddedHex2.Length - 1
        Dim hexDigit As Integer = Convert.ToInt32(paddedHex2(i), 16)
        sb.Append((15 - hexDigit).ToString("X"))
    Next i

    Dim inverted As Integer = Convert.ToInt32(sb.ToString, 16)
    intVal2 = -(inverted + 1)
    resVal2 = intVal2 * res

    'Finally, which result do we use as the final decimal? For our example we get
    'resVal1 (unsigned)=+502.125
    'resVal2 (signed)  =  -9.875
    'Field is signed so is 502.125 > 150? Yes, so use the signed result of -9.875.
    If IsUnsignedInput Then
        'If unsigned then we always expect a positive value so use straight conversion.
        Debug.Print("Result=" & resVal1)
    Else
        'If signed then we expect a positive OR negative value
        If resVal1 > decCeiling Then
            'Standard conversion yields a higher number than expected so use two's complement to get number
            Debug.Print("Result=" & resVal2)
        Else
            'Standard conversion yields a number that is in the expected range so use straight conversion to get number
            Debug.Print("Result=" & resVal1)
        End If
    End If

与遗留系统进行背靠背比较,它们都匹配,但过去不能使用hex,我有点谨慎。对于这种方法的任何进一步反馈,我将不胜感激。

1 个答案:

答案 0 :(得分:4)

intVal = 4093是正确的 final = 130976也是正确的。

FFD也可以解释为-3表示在双补码中(计算机如何存储负值)。 32 * -3 = -96。

FFD               = 111111111101 (binary)

在二进制补码中,当第一位为1时,表示该数字为负数。为了否定数字,首先反转所有位然后加1:

FFD inverted =      000000000010
+ 1          =      000000000011 = 3 (decimal).

由于3是否定数,因此实数必须为-3。

您也可以使用Hex表示法执行此操作。如果第一个十六进制数字是> = 8,则您有一个负数。因此,通过执行以下替换来否定数字:

0 -> F
1 -> E
2 -> D
3 -> C
4 -> B
5 -> A
6 -> 9
7 -> 8
8 -> 7
9 -> 6
A -> 5
B -> 4
C -> 3
D -> 2
E -> 1
F -> 0

(第二列只是以相反的顺序列出十六进制数字。)

因此对于FFD,你得到002(十六进制)。您可以将此十六进制数转换为十进制数并添加1,然后得到3.因为这表示负值,请将其乘以-1。 3 * -1 = -3。

Function ConvertHex(ByVal hexVal As String) As Integer
    If hexVal(0) >= "8"c Then 'We have a negative value in the 2's complement
        Dim sb As New System.Text.StringBuilder(hexVal.Length)
        For i As Integer = 0 To hexVal.Length - 1
            'Convert one hex digit into an Integer
            Dim hexDigit As Integer = Convert.ToInt32(hexVal(i), 16)

            'Invert and append it as hex digit
            sb.Append((15 - hexDigit).ToString("X"))
        Next i

        'Get the inverted hex number as Integer again
        Dim inverted As Integer = Convert.ToInt32(sb.ToString(), 16)

        'Add 1 to the inverted number in order to get the 2's complement
        Return -(inverted + 1)
    Else
        Return Convert.ToInt32(hexVal, 16)
    End If
End Function

但是如果你总是有3个十六进制数字,你可以简单地执行此操作

Function ConvertHex3(ByVal hexVal As String) As Integer
    Dim number = Convert.ToInt32(hexVal, 16)
    If hexVal(0) >= "8"c Then
        Return number - &H1000
    Else
        Return number
    End If
End Function

那更聪明!