【问题标题】:How to decode hex to negative integer value in Perl如何在 Perl 中将十六进制解码为负整数值
【发布时间】:2020-04-07 12:34:51
【问题描述】:

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

9BDCE310
B4D9F1E502
EAB1A9C607
88EE8EB9F9FFFFFFFF01
9E828D89FCFFFFFFFF01

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

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 );
    }

    return $num;
}

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

88EE8EB9F9FFFFFFFF01
9E828D89FCFFFFFFFF01

请帮我修改代码。

【问题讨论】:

    标签: regex perl hex


    【解决方案1】:

    我猜解码后的值是一个 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
    

    请注意,使用的编码方案对于带符号的数字非常低效。

    【讨论】:

    • 优秀,做工很好。你又帮了我的忙。
    猜你喜欢
    • 2020-04-14
    • 1970-01-01
    • 2011-12-10
    • 2019-04-30
    • 2012-08-04
    • 2013-10-30
    • 1970-01-01
    • 2021-09-29
    相关资源
    最近更新 更多