【发布时间】:2020-04-14 18:25:53
【问题描述】:
我对十六进制格式的负整数值有疑问。我的工作有 2 种格式,如下例所示:
###########################################################################
=for comment
B4 80 B5 FF 07 = 2146254900
B5 80 B5 FF 07 = 2146254901
A9 B4 E8 8C 08 = -2120607191
AA B4 E8 8C 08 = -2120607190
A3 86 8D 8E FC FF FF FF FF 01 = -1044167901
A4 86 8D 8E FC FF FF FF FF 01 = -1044167900
=cut
###########################################################################
$vars[0] = "\xB4\x80\xB5\xFF\x07";
$vars[1] = "\xB5\x80\xB5\xFF\x07";
$vars[2] = "\xA9\xB4\xE8\x8C\x08";
$vars[3] = "\xAA\xB4\xE8\x8C\x08";
$vars[4] = "\xA3\x86\x8D\x8E\xFC\xFF\xFF\xFF\xFF\x01";
$vars[5] = "\xA4\x86\x8D\x8E\xFC\xFF\xFF\xFF\xFF\x01";
###########################################################################
for my $var (@vars)
{
print decodeInt($var) . "\n";
}
###########################################################################
sub decodeInt
{
$_[0] =~ s/^([\x80-\xFF]*[\x00-\x7F])// or return;
my $encoded_num = $1;
my $num = 0;
for ( reverse unpack 'C*', $encoded_num )
{
$num = ( $num << 7 ) | ( $_ & 0x7F );
}
$num = unpack 'q', pack 'Q', $num; #Cast two unsigned complement Ints back to 64-bit signed
return $num;
}
##########################################################################
以前,上面的代码运行良好。但是现在我有了新的负整数值格式,它不起作用。
A9 B4 E8 8C 08 = -2120607191
AA B4 E8 8C 08 = -2120607190
我的代码解码为 2174360105 和 2174360106。
【问题讨论】:
-
看起来像 2174360105 - 2^32 = -2120607191
-
再添加一个例子:A1 E1 CE FD 0F = -5001055 不知道怎么判断是不是负值。
-
Re“我不知道如何检查它是否为负值。”,从你显示的数据中无法判断。
-
顺便说一下,你的 decodeInt() 函数修改了它的参数,这通常被认为是一件坏事。这似乎也没有必要。你可以只做一个匹配 m// 而不是替换 s///。
-
@Dave Mitchell,我相信这里说得通。有 BER 编码的数字,它是流的可变长度编码。因此,解码器/提取器从输入中删除编码数字是有意义的,以便可以从编码数字停止的地方继续提取。