You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在PowerShell中将3字节十六进制字符串转换为有符号整数?

解决24位十六进制字符串转有符号整数的问题

你遇到的核心问题是:PowerShell没有原生的24位有符号整数类型,直接用[int32]转换时,会把24位十六进制字符串当成32位无符号数的低24位(自动补0到32位),导致原24位补码的符号位被忽略,无法正确识别负数。

举个例子,你的目标值D35A71是24位补码,最高位字节D3的二进制是11010011,符号位为1,代表负数。但[int32]"0xD35A71"会把它当成0x00D35A71(32位无符号数),结果就是正数13851249,而非预期的-2925967

下面提供两种简便的正确实现方式:

方案1:符号扩展到32位

24位补码转有符号整数的关键是符号扩展:如果原24位的最高位是1(负数),就把32位的高8位全部设为1;如果是0(正数),高8位设为0。

大端格式(最高位字节在前)的处理代码

$hexStr = "D35A71" # 你的24位十六进制字符串(大端)

# 转换为字节数组(过滤split产生的空字符串)
$bytes = ($hexStr -split '(..)' | Where-Object { $_ }) | ForEach-Object { [byte]"0x$_" }

# 执行符号扩展
if ($bytes[0] -band 0x80) {
    # 符号位为1,高8位补0xFF
    $extendedBytes = [byte[]]@(0xFF) + $bytes
} else {
    # 符号位为0,高8位补0x00
    $extendedBytes = [byte[]]@(0x00) + $bytes
}

# 转换为有符号32位整数
$intValue = [BitConverter]::ToInt32($extendedBytes, 0)
Write-Host $intValue # 输出:-2925967

小端格式(最低位字节在前)的处理代码

如果你的十六进制字符串是小端存储(比如你代码中reverse后的715AD3),需要先反转字节数组转为大端,再执行上述逻辑:

$hexStr = "715AD3" # 小端格式的十六进制字符串
$bytes = ($hexStr -split '(..)' | Where-Object { $_ }) | ForEach-Object { [byte]"0x$_" }
[array]::Reverse($bytes) # 转为大端字节数组

# 后续符号扩展步骤同上
if ($bytes[0] -band 0x80) {
    $extendedBytes = [byte[]]@(0xFF) + $bytes
} else {
    $extendedBytes = [byte[]]@(0x00) + $bytes
}

$intValue = [BitConverter]::ToInt32($extendedBytes, 0)
Write-Host $intValue # 输出:-2925967

方案2:利用无符号整数计算补码

另一种思路是先把24位十六进制转成无符号32位整数,再通过补码规则计算有符号值:如果24位的最高位(对应0x800000)为1,就减去2^24(即0x1000000)得到负数结果。

$hexStr = "D35A71" # 大端十六进制字符串
$uintValue = [uint32]"0x$hexStr"

# 判断24位补码的符号位
if ($uintValue -band 0x800000) {
    $intValue = $uintValue - 0x1000000
} else {
    $intValue = [int32]$uintValue
}

Write-Host $intValue # 输出:-2925967

关于你尝试的位运算代码出错的原因

你之前写的位运算代码没得到正确结果,大概率是字节序处理反了:你用了reverse后的字符串去取前两位作为最高位字节,但那其实是小端的最低位字节,导致符号位判断错误。只要调整为大端格式(最高位字节在前),位运算就能正常工作:

$start = "D35A71" # 大端字符串
$byte0 = [sbyte]"0x$($start.Substring(0,2))" # 最高位字节:0xD3 = -45
$byte1 = [byte]"0x$($start.Substring(2,2))" # 中间字节:0x5A = 90
$byte2 = [byte]"0x$($start.Substring(4,2))" # 最低位字节:0x71 = 113

$intValue = ($byte0 -shl 16) -bor ($byte1 -shl 8) -bor $byte2
Write-Host $intValue # 输出:-2925967

内容的提问来源于stack exchange,提问作者sv2hui

火山引擎 最新活动