如何进行64位十六进制/十进制算术并在HEX中输出一个完整的数字作为Perl中的字符串?

前端之家收集整理的这篇文章主要介绍了如何进行64位十六进制/十进制算术并在HEX中输出一个完整的数字作为Perl中的字符串?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要用下面的大十六进制数做一些算术,但是当我尝试输出时我得到溢出错误消息“Hexadecimal number> 0xffffffff non-portable”,有关不可移植的消息,或者最大32位十六进制值FFFFFFFF .

所有这些都意味着标准语言和输出例程只能处理32位值.我需要64位值,并做了很多研究,但我没有发现BOTH启用算术AND以十六进制输出大数字.

  1. my $result = 0x00000200A0000000 +
  2. ( ( $id & 0xFFFFF ) * 2 ) + ( ( $id / 0x100000 ) * 0x40000000 );

所以,对于带有以下值的$id,我应该得到$result:

  1. $id = 0,$result = 0x00000200A0000000
  2. $id = 1,$result = 0x00000200A0000002
  3. $id = 2,$result = 0x00000200A0000004

我怎样才能做到这一点?

以下是我不确定的研究结果,原因如下:

> How can I do 64-bit arithmetic in Perl?
> How can I sum large hexadecimal values in Perl?含糊不清,回答不是确切的,没有例子.
> Integer overflow
非结论性的
> Integer overflow
非结论性的
> bigint
没有关于赋值,算术或输出的信息
> bignum
示例与我的问题无关.
> How can I sprintf a big number in Perl?
给出的示例对我来说不够信息:不处理十六进制
赋值或算术.
> Re: secret code generator
一些使用Fleximal的例子,提到to_str输出
变量但是1)我看不出怎么样
变量被分配了2)我得到了
错误“无法调用方法”to_str“
没有包裹或物品
参考“当我运行我的代码
它.
> String to Hex
使用Math :: BigInt的例子
不适合我 – 仍然得到
溢出错误.
> Is there a 64-bit hex()?
几乎在那里 – 但没有处理
以十六进制输出大数,
它只涉及十进制.
> CPAN Math:Fleximal
做算术,但实际上似乎没有任何手段
输出仍为十六进制的值
> sprintf
似乎无法应付
数字大于32位,得到
饱和的FFFFFFFF消息.

编辑:更新 – 新要求和提供的解决方案 – 请随时提供评论

查斯.欧文斯的答案仍然被接受和优秀(第2部分对我有效,没有尝试过新的Perl的第1部分版本,尽管我会邀请其他人确认).

但是,另一个要求是能够从结果转换回原始id.

所以我写了代码来做这个,这是完整的解决方案,包括@Chas.欧文斯原始解决方案,然后实施这一新要求:

  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5. use bigint;
  6.  
  7. use Carp;
  8.  
  9. sub bighex {
  10. my $hex = shift;
  11.  
  12. my $part = qr/[0-9a-fA-F]{8}/;
  13. croak "$hex is not a 64-bit hex number"
  14. unless my ($high,$low) = $hex =~ /^0x($part)($part)$/;
  15.  
  16. return hex("0x$low") + (hex("0x$high") << 32);
  17. }
  18.  
  19. sub to_bighex {
  20. my $decimal = shift;
  21. croak "$decimal is not an unsigned integer"
  22. unless $decimal =~ /^[0-9]+$/;
  23.  
  24. my $high = $decimal >> 32;
  25. my $low = $decimal & 0xFFFFFFFF;
  26.  
  27. return sprintf("%08x%08x",$high,$low);
  28. }
  29.  
  30. for my $id (0,1,2,0xFFFFF,0x100000,0x100001,0x1FFFFF,0x200000,0x7FDFFFFF ) {
  31. my $result = bighex("0x00000200A0000000");
  32. $result += ( ( $id & 0xFFFFF ) * 2 ) + ( ( $id / 0x100000 ) * 0x40000000 );
  33.  
  34. my $clusterid = to_bighex($result);
  35.  
  36. # the convert back code here:
  37. my $clusterid_asHex = bighex("0x".$clusterid);
  38. my $offset = $clusterid_asHex - bighex("0x00000200A0000000");
  39. my $index_small_units = ( $offset / 2 ) & 0xFFFFF;
  40. my $index_0x100000_units = ( $offset / 0x40000000 ) * 0x100000;
  41. my $index = $index_0x100000_units + $index_small_units;
  42.  
  43.  
  44. print "\$id = ".to_bighex( $id ).
  45. " clusterid = ".$clusterid.
  46. " back to \$id = ".to_bighex( $index ).
  47. " \n";
  48. }

请在http://ideone.com/IMsp6试用此代码.

解决方法

  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. use bigint qw/hex/;
  7.  
  8. for my $id (0,2) {
  9. my $result = hex("0x00000200A0000000") +
  10. ( ( $id & 0xFFFFF ) * 2 ) + ( ( $id / 0x100000 ) * 0x40000000 );
  11. printf "%d: %#016x\n",$id,$result;
  12. }

bigint pragma将hex函数替换为可以处理大数字的版本.它还透明地使数学运算符处理大的int而不是目标平台上的int.

注意,这仅适用于Perl 5.10及更高版本.如果您运行的是早期版本的Perl 5,可以尝试这样做:

  1. #!/usr/bin/perl
  2.  
  3. use strict;
  4. use warnings;
  5. use bigint;
  6.  
  7. use Carp;
  8.  
  9. sub bighex {
  10. my $hex = shift;
  11.  
  12. my $part = qr/[0-9a-fA-F]{8}/;
  13. croak "$hex is not a 64-bit hex number"
  14. unless my ($high,2) {
  15. my $result = bighex("0x00000200A0000000");
  16. $result += ( ( $id & 0xFFFFF ) * 2 ) + ( ( $id / 0x100000 ) * 0x40000000 );
  17. print "$id ",to_bighex($result),"\n";
  18. }

猜你在找的Perl相关文章