我正在努力理解CRC算法。我一直在阅读this tutorial,如果我正确理解它,CRC值只是除法的余数,其中消息用作被除数,除数是预定义的值-用一种特殊的多项式算法执行。它看起来很简单,所以我尝试实现CRC-32:
public static uint Crc32Naive(byte[] bytes)
{
uint poly = 0x04c11db7; // (Poly)
uint crc = 0xffffffff; // (Init)
foreach (var it in bytes)
{
var b = (uint)it;
for (var i = 0; i < 8; ++i)
{
var prevcrc = crc;
// load LSB from current byte into LSB of crc (RefIn)
crc = (crc << 1) | (b & 1);
b >>= 1;
// subtract polynomial if we've just popped out 1
if ((prevcrc & 0x80000000) != 0)
crc ^= poly;
}
}
return Reverse(crc ^ 0xffffffff); // (XorOut) (RefOut)
}
(其中Reverese
函数将位顺序颠倒)
应该类似于以下划分方法(进行一些附加调整):
1100001010
_______________
10011 ) 11010110110000
10011,,.,,....
-----,,.,,....
10011,.,,....
10011,.,,....
-----,.,,....
00001.,,....
00000.,,....
-----.,,....
00010,,....
00000,,....
-----,,....
00101,....
00000,....
-----,....
01011....
00000....
-----....
10110...
10011...
-----...
01010..
00000..
-----..
10100.
10011.
-----.
01110
00000
-----
1110 = Remainder
对于:0x00
函数返回正确的0xd202ef8d
,但对于0x01
-0xd302ef8d
而不是0xa505df1b
(我一直在使用{{3 }}以验证我的结果)。
我的实施解决方案对我来说更有意义:将股息增加1只能将提醒更改为1,对吧?但事实证明,结果看起来应该完全不同。因此,显然我缺少明显的东西。它是什么?改变分红中的最低有效数字会对结果有多大影响?
答案 0 :(得分:0)
这是一个左移CRC的示例,它模拟除法,CRC初始化为0,并且crc没有补码或取反。该示例代码模拟了一个除法,其中4个字节的零被附加到bytes []({bytes [],0,0,0,0}是被除数,除数是0x104c11db7,未使用商,而余数是CRC)。
public static uint Crc32Naive(byte[] bytes)
{
uint poly = 0x04c11db7; // (Poly is actually 0x104c11db7)
uint crc = 0; // (Init)
foreach (var it in bytes)
{
crc ^= (((int)it)<<24); // xor next byte to upper 8 bits of crc
for (var i = 0; i < 8; ++i) // cycle the crc 8 times
{
var prevcrc = crc;
crc = (crc << 1);
// subtract polynomial if we've just popped out 1
if ((prevcrc & 0x80000000) != 0)
crc ^= poly;
}
}
return crc;
}
将CRC初始化为零以外的值是很常见的,但是对CRC进行后补码并不常见,而且我不知道有任何CRC会对CRC进行位反转。
CRC的另一种变化是右移,通常用于模拟硬件,在该硬件中,数据以字节的最低有效位优先发送。