vb.net 将十六进制字符串转换为整数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25774719/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert hex strings to integers
提问by sinDizzy
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:
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)
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.
除了在这种情况下,这一直很好用: hexVal="FFD" 和 fac=32 .NET 给了我 intVal=4093 和 final=130976。然而,我正在检查的遗留系统给出了 -96。
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.
我有点困惑,但理论上它是十六进制表示法。我拥有的关于原始数据的唯一文档说明:字符是按照 ISO Alphabet No 5 编码的,每个字符使用 7 位,也就是说,没有添加奇偶校验位。三个这样的字符将构成每个 32 位字的字段。
Am I converting this incorrectly?
我是否错误地转换了这个?
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
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.
和遗留系统做一个背靠背的比较,它都匹配,但它在过去并没有太多地使用十六进制,我有点谨慎。如果您对此方法有任何进一步的反馈,我将不胜感激。
回答by Olivier Jacot-Descombes
intVal=4093 is correct.
final=130976 is also correct.
intVal=4093 是正确的。
final=130976 也是正确的。
FFDcan also be interpreted as -3 represented in the two's complement (that's how computers store negative values). 32 * -3 = -96.
FFD也可以解释为以二进制补码表示的 -3(这就是计算机存储负值的方式)。32 * -3 = -96。
FFD = 111111111101 (binary)
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:
在二进制补码中,当第一位为 a 时1,表示该数为负数。为了否定这个数字,首先将所有位取反,然后加 1:
FFD inverted = 000000000010
+ 1 = 000000000011 = 3 (decimal).
Since 3 is the negated number, the real number must be -3.
由于 3 是负数,因此实数必须是 -3。
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:
您也可以使用十六进制表示法执行此操作。如果第一个十六进制数字 >= 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
(The second column simply lists the hex digits in reverse order.)
(第二列仅以相反的顺序列出十六进制数字。)
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.
因此,对于 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
But if you always have 3 hex digits you can simply do this
但是如果你总是有 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
That's much smarter!
这更聪明!

