首页 > 解决方案 > 如何在perl中将bigint转换为字节数组,类似于java

问题描述

我正在尝试在 perl 中复制一些 java 代码。

我需要执行的操作是将 Java BigInteger 转换为字节数组

Java 代码:

public class Main {
    public static void main(String[] args) {
         BigInteger n = new BigInteger("1677259342285725925376");
         System.out.println(Arrays.toString(n.toByteArray()));
    }

}

输出:[90, -20, -90, 53, 78, -38, 2, -128, 0]

作为 perl 的新手,尝试搜索并从https://www.perlmonks.org/?node_id=229290获得帮助

Perl 代码:

sub bigint_to_bytearray {
  my $bigint = shift;
  my @bytes;
  while(1) {
    my ($q,$r) = $bigint->brsft(8);
    push(@bytes,$r+0);
    last if $q == 0;
    $bigint = Math::BigInt->new($q);
  }
  return @bytes;
}

$n = new Math::BigInt('1677259342285725925376');
my @array  = bigint_to_bytearray($n);
print "\\tOUTPUT ARRAY  = ", join ', ', @array, "\n";

我收到错误

Use of uninitialized value $r in addition (+) at path/test.pl line 11.
Use of uninitialized value $r in addition (+) at path/test.pl line 11.
Use of uninitialized value $r in addition (+) at path/test.pl line 11.
Use of uninitialized value $r in addition (+) at path/test.pl line 11.
Use of uninitialized value $r in addition (+) at path/test.pl line 11.
Use of uninitialized value $r in addition (+) at path/test.pl line 11.
Use of uninitialized value $r in addition (+) at path/test.pl line 11.
Use of uninitialized value $r in addition (+) at path/test.pl line 11.

标签: arraysperl

解决方案


这不支持负数。

sub bigint_to_bytearray {
   my $bigint = shift;
   die "Negative numbers not supported" if $bigint->is_neg;

   my @bytes = unpack('c*', $bigint->to_bytes);
   unshift @bytes, 0x00 if $bytes[0] < 0;  # Add sign bit if necessary.
   return @bytes;
}

以上需要相对较新版本的 Math::BigInt。以下效率较低,但它适用于更旧的版本:

sub bigint_to_bytearray {
   my $bigint = shift;
   die "Negative numbers not supported" if $bigint->is_neg;

   my @bytes = unpack('c*', pack('H*', substr($bigint->as_hex, 2)));
   unshift @bytes, 0x00 if $bytes[0] < 0;  # Add sign bit if necessary.
   return @bytes;
}

my @bytes = unpack('c*', $bigint->to_bytes);

可以替换为

my @bytes =
   map { $_ >= 0x80 ? 0x100 - $_ : $_ }
      map ord,
         split //,
            $bigint->to_bytes;

my @bytes = unpack('c*', pack('H*', substr($bigint->as_hex, 2)));

可以替换为

my $hex = substr($bigint->as_hex, 2);
$hex = "0$hex" if length($hex) % 2;
my @bytes =
   map { $_ >= 0x80 ? 0x100 - $_ : $_ }
      map hex,
         $hex =~ /../g;

推荐阅读