我正在迭代一组32位十六进制字符串(“DEADBEEF”,“12345678”等等),我试图将它们加在一起形成一个32位校验和。假设变量$temp
在下面的示例中加载了一些十六进制字符串。
my $temp;
my $checksum;
for (...)
{
#assume $temp is loaded with a new hex string here
my $tempNum = hex ($temp);
$checksum += $tempNum;
$checksum &= 0xFFFFFFFF;
print printf("checksum: %08X",$checksum);
}
前几个值是“7800798C”,“44444444”和“44444444”。输出是:
校验和:7800798C
校验和: BC44BDD0
校验和:FFFFFFFF
校验和:FFFFFFFF
等。
你可以看到前两个总结是正确的,然后它似乎饱和。我是否遗漏了有关Perl变量大小限制的内容?
编辑:这是脚本的实际输出(字符串是十六进制字符串,value是该字符串的十进制转换,校验和是结果输出):
string: 7800798C, value: 2013297036, checksum 7800798C string: 44444444, value: 1145324612, checksum BC44BDD0 string: 44444444, value: 1145324612, checksum FFFFFFFF string: 44444444, value: 1145324612, checksum FFFFFFFF string: 78007980, value: 2013297024, checksum FFFFFFFF string: 44444444, value: 1145324612, checksum FFFFFFFF
答案 0 :(得分:6)
如果使用32位整数编译perl
,则导致数字大于0xffffffff
的整数运算将导致问题。例如:
my $x = hex '0x1234567890';
my $y = hex '0x1234567890';
print $x + $y, "\n";
你会得到:
Integer overflow in hexadecimal number at ... Hexadecimal number > 0xffffffff non-portable at ...
使用bignum为更大的整数添加透明支持:
#!/usr/bin/perl
use strict; use warnings;
use bignum qw/hex/;
my $x = hex '0x7800798C';
my $chk;
for (1 .. 10) {
$chk += $x;
$chk &= 0xFFFFFFFF;
printf("checksum: %08X\n", $chk);
}
验证输出符合您的期望:
checksum: 7800798C checksum: F000F318 checksum: 68016CA4 checksum: E001E630 checksum: 58025FBC checksum: D002D948 checksum: 480352D4 checksum: C003CC60 checksum: 380445EC checksum: B004BF78
没有bignum
,我得到:
checksum: 7800798C checksum: F000F318 checksum: FFFFFFFF checksum: FFFFFFFF checksum: FFFFFFFF ...
答案 1 :(得分:6)
之前曾在Perl Monks询问过。
答案似乎是“use integer
”。
请参阅Perl Monks和perldoc integer的原始答案。
$ perl -we 'use integer; printf("%08X\n", 0xFFFF_FFFF + 0xFFFF_FFFF)'
答案 2 :(得分:3)
你想要什么结果? &=
将删除大于0xffffffff
的任何数字位。将数字连续添加在一起只会获得越来越大的数字,然后使用&
进行0xffffffff
。在某些时候,我希望你会得到0xffffffff
以外的东西,不是吗?但它永远不会更大!
制作校验和的更好方法可能是xor
你的数字。
my $temp;
my $checksum;
for (...)
{
#assume $temp is loaded with a new hex string here
my $tempNum = hex ($temp);
$checksum ^= $tempNum;
print printf("checksum: %08X",$checksum);
}
这将使这些数字具有独特性。
答案 3 :(得分:3)
要展开Sinan's answer,&=
运算符和%X
格式都会受到编译到Perl中的整数大小的影响。在这种情况下,两者的最大大小为4294967295或0xFFFFFFFF。
虽然您的变量可以包含大于此值的值,但在通过&=
或sprintf("%X")
时,它们将被截断为此最大值。