我已经将二进制文件的内容读作无符号字节数组,但我想将其中的一些解释为有符号字节。我该怎么做?
#An array of unsigned bytes
[byte[]]$b = @(255)
#This doesn't work
[sbyte]$s = $b[0]
#Neither does this
[sbyte]$s = [convert]::ToSByte($b[0])
我想要的是价值-1
。
答案 0 :(得分:1)
value
大于[sbyte]::MaxValue
, The \[System.Convert\]::ToSByte(value)
method会引发 OverflowException 。
回归理论(Converting from two's complement representation):
$mask = [byte] 0x80 # [math]::pow(2,7)
$b = [byte] 255
$s = [sbyte] ( -($b -band $mask) + ($b -band ( -bnot $mask )) )
'result: {0,4}, {1,4} ( = 0x{0:x2}, 0x{1:x2} )' -f $b, $s
输出:
result: 255, -1 (= 0xff, 0xff )
当然,您可以将计算简化为
$s = [sbyte] ( -($b -band 0x80) + ($b -band 0x7F) )
修改 以反驳PetSerAl's doubts关于的问题。 PetSerAl's doubts是对的:Powershell-ISE的结果与Powershell中的结果不同!该公式应该是(见标记括号)[sbyte] -($b -band $mask) + ($b -band ( -bnot $mask ))
公式正确性
# ↓ ↓
[sbyte] ( -($b -band $mask) + ($b -band ( -bnot $mask )) )
# ↑ ↑
<强>证明强>:
function AsSignedByte { ### taken from PetSerAl's comment to the OQ
param([Byte]$Byte)
[sbyte]$( if($Byte -ge 128) { $Byte - 256 } else { $Byte })
}
$mask = [byte] 0x80 # [math]::pow(2,7)
$good = 0
For ($i = 0 ; $i -lt 256; $i++) {
$b = [byte] $i
$s = [sbyte] ( -($b -band $mask) + ($b -band ( -bnot $mask )) )
$ss = AsSignedByte $b
if ( ($s -ne $ss) -or
($s.GetTypeCode() -ne $ss.GetTypeCode()) -or
($s -isnot [sbyte])) {
'result: {0,4}, {1,4} ( = 0x{0:x2}, 0x{1:x2} )' -f $s, $ss
} else {
$good +=1
}
}
$good
<强>输出强>:
PS D:\PShell> D:\PShell\SO\48085510.ps1
256
PS D:\PShell>