将 HEX 字符串转换为 Unsigned INT (VBA)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40213758/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-12 11:24:50  来源:igfitidea点击:

Convert HEX string to Unsigned INT (VBA)

vbaaccess-vba

提问by SBF

In MSACCESS VBA, I convert a HEX string to decimal by prefixing the string with "&h"

在 MSACCESS VBA 中,我通过在字符串前加上“&h”来将十六进制字符串转换为十进制

?CLng("&h1234")
4660
?CLng("&h80000000")
-2147483648 

What should I do to convert it to an unsigned integer?

我该怎么做才能将其转换为无符号整数?

Using CDbl doesn't work either:

使用 CDbl 也不起作用:

?CDbl("&h80000000")
-2147483648 

采纳答案by Slai

Your version seems like the best answer, but can be shortened a bit:

你的版本似乎是最好的答案,但可以缩短一点:

Function Hex2Dbl(h As String) As Double
    Hex2Dbl = CDbl("&h0" & h) ' Overflow Error if more than 2 ^ 64
    If Hex2Dbl < 0 Then Hex2Dbl = Hex2Dbl + 4294967296# ' 16 ^ 8 = 4294967296
End Function

Doublewill have rounding precision error for most values above 2 ^ 53 - 1 (about 16 decimal digits), but Decimalcan be used for values up to 16 ^ 12 - 1 (Decimaluses 16 bytes, but only 12 of them for the number)

Double对于 2 ^ 53 - 1 以上的大多数值(大约 16 位十进制数字),将有舍入精度误差,但Decimal可用于高达 16 ^ 12 - 1 的值(Decimal使用 16 个字节,但只有 12 个用于数字)

Function Hex2Dec(h)
    Dim L As Long: L = Len(h)
    If L < 16 Then               ' CDec results in Overflow error for hex numbers above 16 ^ 8
        Hex2Dec = CDec("&h0" & h)
        If Hex2Dec < 0 Then Hex2Dec = Hex2Dec + 4294967296# ' 2 ^ 32
    ElseIf L < 25 Then
        Hex2Dec = Hex2Dec(Left$(h, L - 9)) * 68719476736# + CDec("&h" & Right$(h, 9)) ' 16 ^ 9 = 68719476736
    End If
End Function

回答by arcadeprecinct

If you want to go higher than 2^31 you could use Decimalor LongLong. LongLongand CLngLngonly work on 64bit platforms though. Since I only have 32 bit office at the moment, this is for Decimaland CDec.

如果你想高于 2^31,你可以使用DecimalLongLongLongLong并且CLngLng只能在 64 位平台上工作。由于我目前只有 32 位办公室,这是为DecimalCDec

There seems to be an issue when converting 8-digit Hex numbers because apparently signed 32-bit is used somewhere in the process which results in the sign mistake even though Decimalcould handle the number.

转换 8 位十六进制数字时似乎存在问题,因为在过程中的某处使用了明显有符号的 32 位,即使Decimal可以处理数字,也会导致符号错误。

'only for positive numbers
Function myHex2Dec(hexString As String) As Variant
    'cut off "&h" if present
    If Left(hexString, 2) = "&h" Or Left(hexString, 2) = "&H" Then hexString = Mid(hexString, 3)

    'cut off leading zeros
    While Left(hexString, 1) = "0"
        hexString = Mid(hexString, 2)
    Wend

    myHex2Dec = CDec("&h" & hexString)
    'correct value for 8 digits onle
    If myHex2Dec < 0 And Len(hexString) = 8 Then
        myHex2Dec = CDec("&h1" & hexString) - 4294967296#
    'cause overflow for 16 digits
    ElseIf myHex2Dec < 0 Then
        Error (6) 'overflow
    End If

End Function

Test:

测试:

Sub test()
    Dim v As Variant
    v = CDec("&H80000000")              '-2147483648
    v = myHex2Dec("&H80000000")         '2147483648
    v = CDec("&H7FFFFFFFFFFFFFFF")      '9223372036854775807
    v = myHex2Dec("&H7FFFFFFFFFFFFFFF") '9223372036854775807
    v = CDec("&H8000000000000000")      '-9223372036854775808
    v = myHex2Dec("&H8000000000000000") 'overflow

End Sub

回答by SBF

With remark of @arcadeprecinct I was able to create a function for it:

通过@arcadeprecinct 的评论,我能够为它创建一个函数:

Function Hex2UInt(h As String) As Double
    Dim dbl As Double: dbl = CDbl("&h" & h)

    If dbl < 0 Then
        dbl = CDbl("&h1" & h) - 4294967296#
    End If

    Hex2UInt = dbl
End Function

Some example output:

一些示例输出:

?Hex2UInt("1234")
4660 
?Hex2UInt("80000000")
2147483648 
?Hex2UInt("FFFFFFFFFFFF")
281474976710655 

Maximum value to represent as an integer is 0x38D7EA4C67FFF

表示为整数的最大值是 0x38D7EA4C67FFF

?Hex2UInt("38D7EA4C67FFF")
999999999999999 
?Hex2UInt("38D7EA4C68000")
1E+15 

回答by h2so4

a proposal, result in h

一个提议,结果是 h

sh = "&H80000000"
h = CDbl(sh)
If h < 0 Then
 fd = Hex$(CDbl(Left(sh, 3)) - 8)
 sh = "&h" & fd & Mid(sh, 4)
 h = CDbl(sh) + 2 ^ 31
End If