将字节数组(十六进制)转换为有符号 Int

问题描述 投票:0回答:1

我正在尝试将(可变长度)十六进制字符串转换为有符号整数(我需要正值或负值)。

[Int16] [int 32] 和 [int64] 似乎可以很好地处理 2,4+ 字节长度的十六进制字符串,但我只能使用 3 字节字符串 [int24](在 powershell 中没有这样的命令)。

这是我现在拥有的(片段):

$start = $mftdatarnbh.Substring($DataRunStringsOffset+$LengthBytes*2+2,$StartBytes*2) -split "(..)"
[array]::reverse($start)
$start = -join $start

if($StartBytes*8 -le 16){$startd =[int16]"0x$($start)"}
elseif($StartBytes*8 -in (17..48)){$startd =[int32]"0x$($start)"}
else{$startd =[int64]"0x$($start)"}

使用上面的代码,$start 值“D35A71”给出“13851249”而不是“-2925967”。我试图找出一种实现二进制补码的方法,但迷失了。有什么简单的方法可以做到这一点吗?

提前谢谢您

编辑:基本上,我认为我需要实现这样的东西:

int num = (sbyte)array[0] << 16 | array[1] << 8 | array[2];

此处所示。

刚刚尝试过这个:

$start = "D35A71"
[sbyte]"0x$($start.Substring(0,2))" -shl 16 -bor "0x$($start.Substring(2,2))" -shl 8 -bor "0x$($start.Substring(4,2))"

但似乎没有得到正确的结果:-/

powershell type-conversion hex powershell-4.0
1个回答
4
投票

要将十六进制数字字符串解析为数字,您可以使用[bigint]

System.Numerics.BigInteger
):

# Since the most significant hex digit has a 1 as its most significant bit # (is >= 0x8), it is parsed as a NEGATIVE number. # To force unconditional interpretation as a positive number, prepend '0' # to the input hex string. PS> [bigint]::Parse('D35A71', 'AllowHexSpecifier') -2925967
您可以将生成的 

[bigint]

 实例转换回 
[int]
 (
System.Int32
)。

注:

  • 结果是一个数,因为十六进制输入字符串的最重要的十六进制数字>= 0x8

    (二进制1000
    ),即设置了
    高位(含义:最组成给定十六进制数字的 4 位的有效位是 1
    )。

      强制
    • [bigint]
       无条件解释十六进制。输入字符串作为
      正数数字,前置0
  • 结果数的内部补码表示是在字节边界执行的,因此给定的十六进制数具有奇数位数(即,如果第一个十六进制数字是“半字节”)缺失的半字节由 1

     位填充。

  • 因此,

    最高有效位为 >= 0x8

    (解析为 
    数)的十六进制数字字符串会导致 相同数作为前置 一个或多个 F
    s (
    0xF
     = = 
    1111
    )到它
    ;例如,以下调用
    all 会导致 -2048
    :

    [bigint]::Parse('800', 'AllowHexSpecifier')
    ,

    [bigint]::Parse('F800', 'AllowHexSpecifier')
    ,

    [bigint]::Parse('FF800', 'AllowHexSpecifier'
    ),...

有关解析逻辑的详细信息,请参阅

文档


示例:

# First digit (7) is < 8 (high bit NOT set) -> positive number [bigint]::Parse('7FF', 'AllowHexSpecifier') # -> 2047 # First digit (8) is >= 8 (high bit IS SET) -> negative number [bigint]::Parse('800', 'AllowHexSpecifier') # -> -2048 # Prepending additional 'F's to a number that parses as # a negative number yields the *same* result [bigint]::Parse('F800', 'AllowHexSpecifier') # -> -2048 [bigint]::Parse('FF800', 'AllowHexSpecifier') # -> -2048 # ... # Starting the hex-number string with '0' # *unconditionally* makes the result a *positive* number [bigint]::Parse('0800', 'AllowHexSpecifier') # -> 2048
    
© www.soinside.com 2019 - 2024. All rights reserved.