将十六进制字符串转换为整数 [英] Convert hex strings to integers

查看:162
本文介绍了将十六进制字符串转换为整数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Visual Basic 2010: Recently in one of my projects I have been tasked with reading several data fields in hex. Each field is three characters long. So this is what I have been doing:

'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和final = 130976.但是,我要检查的旧系统给出了-96.

This has been working great except in this case: hexVal="FFD" and fac=32 .NET gives me intVal=4093 and the final=130976. However the legacy system I am checking against gives a -96.

我有点困惑,但可以认为它是十六进制表示法.我只有原始数据状态的文档:字符是按ISO字母No 5编码的,每个字符使用7位,即不添加奇偶校验位.每个32位字的字段将由三个这样的字符组成.

I'm a bit confused but theorize that it's in the hex notation. The only documentation I have for the raw data states: Characters are coded per ISO Alphabet No 5 using seven bits per character, that is, without the addition of a parity bit. Three such characters will comprise the field of each 32-bit word.

我转换不正确吗?

附录:我研究了字段的定义,发现几乎所有的字段都是肯定的(或未签名的).少数可以是负数或正数(带符号).查看旧版代码,他们为每个十六进制字段计算一个未签名的结果和一个签名的结果.如果期望该字段始终为正,则他们使用无符号结果.现在,如果期望该字段为负或正,则他们将采用未签名的结果;如果高于上限,则将使用已签名的结果,否则将使用未签名的结果.这是到目前为止我从下面获得的摘录的内容:

Addendum: I have looked into the definitions of the fields and have discovered that almost all are expected to be positive (or unsigned). A few can be negative or positive (signed). Looking at the legacy code, for each hex field they compute a unsigned result and a signed result. If the field is expected to be always positive then they use the unsigned result. Now if the field is expected to be negative or positive then they take the unsigned result and if higher than a ceiling then they use the signed result, otherwise they use the unsigned result. Here is what I have so far with the snippets from below:

    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的工作量不大,我有点谨慎.对于此方法的任何进一步反馈,我将不胜感激.

Doing a back-to-back comparison with the legacy system it all matches up, but it is not working with hex too much in the past, and I am a little cautious. I would appreciate any further feedback on this approach.

推荐答案

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

intVal=4093 is correct.
final=130976 is also correct.

FFD 也可以解释为-3,以二进制补码表示(这是计算机存储负值的方式).32 * -3 = -96.

FFD can also be interpreted as -3 represented in the two's complement (that's how computers store negative values). 32 * -3 = -96.

FFD               = 111111111101 (binary)

在两者的补码中,当第一位为 1 时,表示数字为负.为了取反数字,首先将所有位取反,然后加1:

In the two's complement, when the first bit is a 1, it means that the number is negative. In order to negate the number, first invert all the bits and then add 1:

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

由于3是负数,因此实数必须为-3.

Since 3 is the negated number, the real number must be -3.

您也可以用十六进制表示法执行此操作.如果第一个十六进制数字> = 8,则为负数.因此,通过执行以下替换来取反数字:

You can do this in the Hex notation as well. If the first hex digit is >= 8, you have a negative number. So negate the number by doing the following replacements:

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

(第二列仅以相反的顺序列出了十六进制数字.)

(The second column simply lists the hex digits in reverse order.)

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

So for FFD you get 002 (hex). You can convert this hex number into a decimal number and add 1 and you get 3. Because this represents a negative value, multiply it by -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个十六进制数字,则只需执行此操作

But if you always have 3 hex digits you can simply do this

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

那要聪明得多!

这篇关于将十六进制字符串转换为整数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆