我已多次尝试根据理论编写自己的CRC32实现,但我从未得到预期的结果。
今天我又做了一次尝试,不仅提到了理论,还提到了Boosts的实施。虽然我最终使它正常工作,但我不明白为什么它会这样工作。
我理解为什么boost会反转字节并反转结果,我知道为什么它的初始余数是0xffffffff,结果应该与0xffffffff进行异或。这是标准。
但当它进入函数ProcessBit
时,我就陷入困境。
在How is a CRC32 checksum calculated?的答案中,我找到了一个完整的例子。所以我认为ProcessBit
的实现如下:
void CRC32::ProcessBit(bool b)
{
/*
x xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxb : x curVal, b coming bit
1 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy : y polynomial
*/
if (_remainder & 0x80000000) {
_remainder <<= 1;
_remainder |= b;
_remainder ^= polynomial;
} else {
_remainder <<= 1;
_remainder |= b;
}
}
因为多项式的第一位是1,如果余数从第1位开始,我将对它进行异或。但是这种实现会产生错误的结果。我在Boost中跟踪代码以了解它是如何工作的,并编写我自己的代码:
void CRC32::ProcessBit(bool b)
{
bool high = (_remainder & 0x80000000) ? true : false;
_remainder <<= 1;
if (high != b) {
_remainder ^= polynomial;
}
}
此实施效果很好。但我不明白为什么。令我困惑的是,确定余数是否应与多项式进行异或的条件是:
“余数的第一位等于即将到来的位”。
而在“完整示例”中使用另一个条件,即:
“余数的第一位是1”。
另一个问题是;为什么即将到来的位不会在Boost实现中的余数末尾附加。
修改 我已经解决了这个问题。它产生错误结果的原因是我误解了“初始值”的含义。