2

32 ビットの 16 進数文字列 ("DEADBEEF"、"12345678" など) のセットを反復処理しており、それらを合計して 32 ビットのチェックサムを形成しようとしています。$temp以下の例では、変数が何らかの 16 進文字列でロードされていると仮定します。

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

等..

ご覧のとおり、最初の 2 つの合計は正しく、その後飽和しているように見えます。Perl 変数のサイズ制限に関して何か不足していますか?

EDIT : これはスクリプトからの実際の出力です (文字列は 16 進文字列、値はその文字列の 10 進数変換、チェックサムは結果の出力です):

文字列: 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

が 32 ビット整数でコンパイルされている場合、perlより大きな数になる整数演算0xffffffffは問題を引き起こします。例えば:

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

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

あなたは得るでしょう:

... での 16 進数の整数オーバーフロー
16 進数 > 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

Sinan's answerを拡張するには、&=演算子と形式の両方%Xが、Perl にコンパイルされた整数のサイズの影響を受けます。この場合、いずれかの最大サイズは 4294967295 または 0xFFFFFFFF です。

&=変数はこれより大きな値を保持できますが、またはを介し​​て渡されると、この最大値に切り捨てられsprintf("%X")ます。

于 2009-11-24T14:34:17.820 に答える
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 に答える