in reply to Re^2: CRC of a string
in thread CRC of a string

String::CRC32 is not performing the same calculation as you. If you just need a CRC, I thought it might do.

Since you appear to need the specific CRC of your calculations, Math::BigInt allows you to avoid the integer overflow.

Replies are listed 'Best First'.
Re^4: CRC of a string
by Dirk80 (Pilgrim) on Nov 18, 2009 at 16:00 UTC

    Ok, I did not know that there exist different versions of how to compute a CRC32. But unfortunately I need this specific one.

    Thank you very much for the hint with the Math::BigInt. Now I could get rid of the warnings.

    Here the new code:

    #!/usr/bin/perl use strict; use warnings; use Math::BigInt; # solution: 990644297 my $buffer = "/etc/test2.sh"; my $crc = Math::BigInt->new('0'); &determineCrc32($buffer, $crc); print $crc . "\n"; sub determineCrc32() { my $buffer = $_[0]; my $crc = $_[1]; my $i = 0; my $val = 0; my $k = 0; for( $i = 0; $i < int(length($buffer) / 4); $i = $i + 1 ) { $val = sprintf("%02X", ord(substr($buffer, ($i*4) + 0, 1))) . sprintf("%02X", ord(substr($buffer, ($i*4) + 1, 1))) . sprintf("%02X", ord(substr($buffer, ($i*4) + 2, 1))) . sprintf("%02X", ord(substr($buffer, ($i*4) + 3, 1))); $crc->badd(hex($val)); $crc->bmod('0x100000000'); } $val = ""; $k = 0; for( 1 .. int(length($buffer) % 4) ) { $val .= sprintf("%02X", ord(substr($buffer, ($i*4) + $k, 1))); $k++; } # pad other bytes of 32bit with "00" for( 1 .. (4 - int(length($buffer) % 4)) ) { $val .= "00"; } $crc->badd(hex($val)); $crc->bmod('0x100000000'); }

    Would be very interesting for me how a good perl programmer would code this specific CRC. Because I don't think that my solution is a good way to solve it.

    Greetings

    Dirk
      use strict; # solution: 990644297 my $buffer = "/etc/test2.sh"; my $crc = 0; for (grep $_, split /(.{1,4})/, $buffer) { my $val = sprintf "%02X"x4, map { ord } split //, $_; $crc += hex($val); $crc %= 2**32; } print $crc,$/;

        /(.{1,4})/
        should be
        /(.{1,4})/s

        grep $_, split /(.{1,4})/s, $buffer
        is buggy. Fix:
        $buffer =~ /(.{1,4})/sg
        So much simpler too!

        hex sprintf "%02X"x4, map { ord } split //, $_
        can be simplified to
        unpack 'N', "$_\0\0\0"
        The latter should be much faster too.