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和final = 130976。但是,我要检查的旧系统给出-96。
我有点困惑,但可以认为它是十六进制表示法。我只有原始数据状态的文档:字符是按ISO字母No 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
与传统系统进行背对背比较,所有这些都匹配,但是过去使用十六进制的工作量不大,我有点谨慎。对于此方法的任何进一步反馈,我将不胜感激。
intVal = 4093是正确的。
final = 130976也正确。
FFD
也可以解释为以-2的补码表示的-3(这就是计算机存储负值的方式)。32 * -3 = -96。
FFD = 111111111101 (binary)
在两者的补码中,当第一位为a时1
,表示数字为负。为了取反数字,首先将所有位取反,然后加1:
FFD inverted = 000000000010
+ 1 = 000000000011 = 3 (decimal).
由于3是负数,因此实数必须为-3。
您也可以用十六进制表示法执行此操作。如果第一个十六进制数字> = 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
那更聪明!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句