我曾多次尝试根据理论编写自己的 CRC32 实现,但始终没有得到预期的结果。
今天我又做了一次尝试,不仅参考了理论,还参考了 Boosts 的实现。虽然我终于让它正常工作,但我不明白为什么它会这样工作。
我明白为什么 boost 会反转字节并反转结果,我知道为什么它的初始余数是 0xffffffff 并且结果应该与 0xffffffff 异或。这是标准。但是当它到达功能时ProcessBit
,我被卡住了。
在如何计算 CRC32 校验和的答案中?,我找到了一个完整的例子。所以我认为的实现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 的实现中不会在剩余部分的末尾附加即将到来的位。
编辑: 我已经解决了这个问题。它产生错误结果的原因是我误解了“初始值”的含义。