CRC-32算法如何工作?

时间:2013-11-11 16:21:41

标签: algorithm crc

在对CRC-32算法进行一些研究之后,我得到了以下内容:

/* Usage: Recursively call this with previous crc. Start with crc = 0. */
#define POLYNOMIAL 0x04C11DB7

unsigned int crc32( unsigned int crc, char* msg, unsigned int len ) {
  for ( unsigned int byteNum = 0; byteNum < len; byteNum++ ) {
    char msgByte = msg[ byteNum ];

    for ( unsigned int bitNum = 0; bitNum < 8; bitNum++ ) {
      char msgBit = ( msgByte >> ( 7 - bitNum ) ) & 0x1;

      if ( ( crc & 0x80000000 ) != 0 )
        crc = ( ( crc << 1 ) | msgBit ) ^ POLYNOMIAL;
      else
        crc = ( crc << 1 ) | msgBit;
    }
  }
  return crc;
}

然而,我的代码输出完全不同于常用的CRC-32功能(用表优化)

现在我希望有人可以给我一些CRC-32算法的示例源代码,它不是通过表格优化的,并且可以很好地了解它的实际工作原理。

谢谢,
丹尼斯

5 个答案:

答案 0 :(得分:1)

CRC-32算法将输入视为基数2中的大多数。每个输入位是x的一个幂的系数。例如,最后一位是x ^ 0的系数,最后一位是x ^ 1的系数,依此类推。

该多项式除以生成多项式,其具有度32(即,最高幂是x ^ 32)。所有计算都在场GF(2)上的多项式环中进行。使用中有不同的生成多项式,因此实际上不存在一种CRC-32算法。它们在其他方面也有所不同(例如位顺序)。

CRC-32值是该多项式除法的余数,是多数度为31的多项式,再次由其系数的位表示。

答案 1 :(得分:1)

这看起来不对:

if ( ( crc & 0x80000000 ) != 0 )
    crc ^= POLYNOMIAL;
crc = ( crc << 1 ) | msgBit;

你需要在移位之前测试crc高位,但是在移位并插入消息位之后,对其余的POLYNOMIAL 进行测试。

请注意,实际多项式为0x104C11DB7,并且位32中的1取消0x80000000 << 1(测试证明已设置)

答案 2 :(得分:1)

在档案馆等中使用的那个看起来像这样:

char msg[] = "hello, world!";
uint POLY = 0xEDB88320;

int main( void ) {
  uint i,j,l,x;
  l = sizeof(msg)-1;
  x = 0;
  for( i=0; i<l; i++ ) {
     x = x ^ msg[i];
     for( j=0; j<8; j++ ) {
       x = (x>>1) ^ 0x80000000 ^ ((~x&1)*POLY);
     }
  }
  printf( "crc32(\"%s\")=%08X\n", msg, x );
}

http://rextester.com/EHM45452

或者

x = 0;
for( i=0; i<l; i++ ) {
   x = x ^ (msg[i]^0xFF);
   for( j=0; j<8; j++ ) {
     x = (x>>1) ^ ((x&1)*POLY);
   }
   x ^= 0xFF000000;
}

答案 3 :(得分:1)

您可以了解有关CRC如何工作和实施的所有信息here。或者为了抱怨链接的stackoverflow警察的利益,herehereherehere

答案 4 :(得分:0)

我偶然发现以下pdf:stigge.org/martin/pub/SAR-PR-2006-05.pdf
第18页包含我的解决方案。

由于一些奇怪的原因,我转移到了错误的一边,多项式应该反转。

这是给出正确输出的代码:

/* Usage: Recursively call this with previous crc. Start with crc = 0. */

#define POLYNOMIAL 0xEDB88320

unsigned int crc32( unsigned int crc, char* msg, unsigned int len ) {
  crc ^= 0xFFFFFFFF;
  for ( unsigned int byteNum = 0; byteNum < len; byteNum++ ) {
    char msgByte = msg[ byteNum ];

    for ( unsigned int bitNum = 0; bitNum < 8; bitNum++ ) {
      if ( ( crc ^ msgByte ) & 1 )
        crc = ( crc >> 1 ) ^ POLYNOMIAL;
      else
        crc >>= 1;
      msgByte >>= 1;
    }
  }
  return crc ^ 0xFFFFFFFF;
}