如何在 Perl 中将十六进制解码为负整数值

How to decode hex to negative integer value in Perl

我有以下十六进制数据格式:

9BDCE310
B4D9F1E502
EAB1A9C607
88EE8EB9F9FFFFFFFF01
9E828D89FCFFFFFFFF01

通常,我使用以下代码解码回整数:

sub decodeInt
{
    $_[0] =~ s/^([\x80-\xFF]*[\x00-\x7F])// or return;

    my $encoded_num = ;
    my $num = 0;
    for ( reverse unpack 'C*', $encoded_num )
    {
        $num = ( $num << 7 ) | ( $_ & 0x7F );
    }

    return $num;
}

但它不适用于带符号的负整数值(最后 2 个数据)。

88EE8EB9F9FFFFFFFF01
9E828D89FCFFFFFFFF01

请帮我修改代码

我猜解码值是一个转换为无符号的 64 位有符号二进制补码整数。在二进制补码机上,您可以使用以下命令将其强制转换:

$num = unpack 'q', pack 'Q', $num;

例如,

use strict;
use warnings;
use feature qw( say );

use Config qw( %Config );

sub decode_int {
    my ($encoded_num) = @_;

    my $num = 0;
    $num = ( $num << 7 ) | ( $_ & 0x7F )
       for reverse unpack 'C*', $encoded_num;

    $num = unpack 'q', pack 'Q', $num;

    return $num;
}

{
   $Config{ivsize} >= 8 && $Config{uvsize} >= 8
      or die("64-bit int support required\n");

   say decode_int(pack('H*', $_))
      for qw(
         9BDCE310
         B4D9F1E502
         EAB1A9C607
         88EE8EB9F9FFFFFFFF01
         9E828D89FCFFFFFFFF01
      );
}

产出

35188251
750546100
2026526954
-1759267064
-1054654178

请注意,使用的编码方案对于有符号数来说效率非常低。