2

我正在迭代一组 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

ETC..

正如你所看到的,前两个总和是正确的,然后它似乎饱和了。我是否遗漏了有关 Perl 变量大小限制的内容?

编辑:这是脚本的实际输出(字符串是十六进制字符串,值是该字符串的十进制转换,校验和是结果输出):

字符串:7800798C,值:2013297036,校验和7800798C
字符串:44444444,值:1145324612,校验和BC44BDD0
字符串:44444444,值:1145324612,校验和FFFFFFFF
字符串:44444444,值:1145324612,校验和FFFFFFFF
字符串:78007980,值:2013297024,校验和FFFFFFFF
字符串:44444444,值:1145324612,校验和FFFFFFFF
4

4 回答 4

7

之前在Perl Monks上有人问过这个问题。

答案似乎是“ use integer”。

请参阅 Perl Monks 和perldoc integer的原始答案。

$ perl -we 'use integer; printf("%08X\n",  0xFFFF_FFFF + 0xFFFF_FFFF)'
于 2009-11-24T14:52:22.107 回答
6

如果您perl使用 32 位整数编译,导致数字大于的整数运算0xffffffff将导致问题。例如:

my $x = hex '0x1234567890';
my $y = hex '0x1234567890';

print $x + $y,  "\n";

你会得到:

十六进制整数溢出...
十六进制数 > 0xffffffff 不可移植...

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

验证输出是否符合您的期望:

校验和:7800798C
校验和:F000F318
校验和:68016CA4
校验和:E001E630
校验和:58025FBC
校验和:D002D948
校验和:480352D4
校验和:C003CC60
校验和:380445EC
校验和:B004BF78

没有bignum,我得到:

校验和:7800798C
校验和:F000F318
校验和:FFFFFFFF
校验和:FFFFFFFF
校验和:FFFFFFFF
...
于 2009-11-24T14:28:31.157 回答
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);
}

这将使这些数字具有独特性。

于 2009-11-24T14:28:49.033 回答
3

为了扩展思南的答案&=运算符和%X格式都受到编译成 Perl 的整数大小的影响。在这种情况下,最大大小为 4294967295 或 0xFFFFFFFF。

虽然您的变量可以保存大于此值的值,但通过&=or时它们将被截断到此最大值sprintf("%X")

于 2009-11-24T14:34:17.820 回答