在过去的几天里,我一直在努力了解CRC的工作原理。我坚持使用推荐用于其实现的特定优化。
我的理解:
* CRC是多项式除法,其中位表示x的幂。我可以进行除法(使用常规多项式除法或使用位)并正确地获得CRC。
*移位寄存器用于保存余数。它是n位(对于n次多项式),因为每次减法最多影响n位。一旦整个消息通过寄存器输入,它就包含除法余数。
我被困在哪里:
在此页面上: http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks 实现部分有一些伪代码。我对第一个伪代码和它的两个问题很好(虽然第一个很容易解决)。我无法理解第二个,以及xor的关联性/可交换性如何帮助。手工,我看到第二个伪代码有效,但为什么呢?
其他来源: 其他一些文章给出了相同的优化(将寄存器左侧的位输入而不是右侧)。特别是这篇文章: http://www.ross.net/crc/download/crc_v3.txt 在第10节中做了它(文本搜索词损坏)。除了这是用表格做的,我还没有为桌子做好准备!它确实说最后的n次迭代只用于将消息的尾部放到寄存器的左边,我明白了,但我再次无法理解这里的优化。
编辑:我找到了另一个参考文献(第8页): http://www.hackersdelight.org/crc.pdf 但这个仍然无济于事。它表示预乘与后乘相同,但我不知道这是如何实现的,因为当寄存器左边找到1位时,这会改变寄存器中的位(触发a减法)。
感谢。我非常感谢你对我好奇心的帮助!
丹
答案 0 :(得分:2)
在第一个伪代码中,余数用输入位串的前导部分初始化。然后在迭代期间,在每个步骤中,余数被上移,并且现在空的底部位用来自输入位串的下一位填充。要完成操作,输入位串需要附加零。这些零将在计算过程中通过余数有效地清除数据。
在第二个伪代码中,余数开始清零(充满零)。在迭代期间,来自输入位串的下一位直接放置在余数中的顶部位置。因此,完成计算不需要初始化和刷新。此外,重新排序顶部位的测试和剩余操作的上移。
您可以在几个转换步骤中将第一个伪代码算法转换为第二个伪代码算法,如下所示。
从基本算法的伪代码开始(代码片段1):
function crc(bit array bitString[1..len], int len) {
remainderPolynomial := polynomialForm(bitString[1..n]) // First n bits of the message
for i from 1 to len {
remainderPolynomial := remainderPolynomial * x + bitString[i+n] * x0 // Define bitString[k]=0 for k>len
if coefficient of xn of remainderPolynomial = 1 {
remainderPolynomial := remainderPolynomial xor generatorPolynomial
}
}
return remainderPolynomial
}
第一个转换是交换更新余数多项式的顺序并测试最高位,即我们可以测试第二个顶部位(在向上移位之前),然后在if
分支更新xor之前的余数使用生成多项式,并添加else
分支,该分支也更新余数(如果最高位为零)。此外,请注意,余数的更新基本上是对其进行上移,然后将空的底部位设置为输入位串的下一位。因此+
操作基本上是0 + ?
,这相当于0 xor ?
。通过应用这些原则,我们现在得到以下等效的伪代码:
function crc(bit array bitString[1..len], int len) {
remainderPolynomial := polynomialForm(bitString[1..n]) // First n bits of the message
for i from 1 to len {
if coefficient of xn-1 of remainderPolynomial = 1 {
remainderPolynomial := (remainderPolynomial * x xor bitString[i+n] * x0) xor generatorPolynomial
} else {
remainderPolynomial := remainderPolynomial * x xor bitString[i+n] * x0
}
}
return remainderPolynomial
}
现在,请注意,在循环中,我们将butstring[i+n]
置于x0
位置。然后在随后的计算期间该位向上移位。我们可以在概念上将bitString[i+n] * x0
更改为bitString[i] * xn
。如果我们从if/else
分支中取出并在向上移动余数(... * x
)之前执行此操作,我们会得到... xor bitString[i] * xn-1
。因为我们现在将输入位串的位置于余数的顶部,所以我们只需在开头清除余数,而不需要附加零来通过余数寄存器清除数据。瞧,我们现在有修改算法的伪代码(代码片段2):
function crc(bit array bitString[1..len], int len) {
remainderPolynomial := 0
for i from 1 to len {
remainderPolynomial := remainderPolynomial xor (bitstring[i] * xn-1)
if (coefficient of xn-1 of remainderPolynomial) = 1 {
remainderPolynomial := (remainderPolynomial * x) xor generatorPolynomial
} else {
remainderPolynomial := remainderPolynomial * x
}
}
return remainderPolynomial
}