您的位置:首页 > 其它

轻松理解CRC差错检测算法七 -注解

2016-12-22 22:47 357 查看

原文第9部分的补充

原因

不得不承认把这个系列的翻译继续下去是很有挑战的。最近加班多,工作之余的精力就比较少了。坚持下去的想法还是有的,但回顾渐忘的初心,做这件事情的意义是在于帮助那些想把CRC算法学明白,而英文又差那么一点的人们,帮助他们从最根本的原理上来理解这个算法系列。我在之前自己看的过程中就发现作者的思路时有跳跃性。我自己在看的时候思路经常出现断续,作者说的标题“轻松理解”其实是有点夸大了。不符合我的习惯,我的习惯是每一个演进,都有它的原理在里面,可以直接看到,不需要读者再去思考。所以有了写这篇注解动机。

为了保持译文的完整和原本的条理,不方便直接在原文中加入大量的注解,另外只有证明我自己确实是理解了这部分,才能说明我翻译的基础是牢固的。所以才有了这一篇,作为原文第9节的注解。这里我会把我理解这部分的思路一步步展现出来。

原文梳理

第9节作为第8节的进一步,远远没有第8节那么容易理解。第8节,在讲解基本的直接实现的算法,其原理也非常简单,与长除法对应,也就是用移位与异或来实现长除法。第9节中,在第8节直接实现的基础上,作者介绍了表驱动实现。他的思路是,介绍表驱动的2个基础理论



1. 由poly和信息的前8位,可以确定第8次迭代后,寄存器的最高位值是0或者1。

2. 一个特定数a多次在不同的偏移位置与同一数b相异或,得到的结果,与a经过相同的偏移的值相异或后,再与b相异或得到的结果相同。用公式表达就是:

[(a << 1) ^ b] ^ a ^ (a << 2) ^ (a << n) =

[(a << 1) ^ a ^ (a << 2) ^ (a << n)] ^ b

有了这样的两个条件后,然后实然一下,作者不厚道地把表驱动实现的伪代码摆了出来。这里的跳跃性太大了,相信许多原文的人都没有搞明白。我要做的就是把这部分空白补上。

填补空白

填补之前,我们还是把思路再前移动一个环节看下,为什么长除法可以用移位+异或来实现。这样我们的思路就前后衔接,完美无瑕。

这个图中展示出的是长除法的计算过程。用伪代码来描述就是:

1. 把W位除数与被除数左对齐。

2. 如果被除数不小于除数,即被除数最高位是1,执行第3步。否则执行第4步。

3. 执行与除数的CRC减法(异或)运算。得到一个差值,这个差值长度一定比除数要短1,即W-1。跳到第5步。

4. 把除数全部位设0,执行CRC减法运算,自右向左保留W-1位。跳到第5步。

5. 如果被除数后面还有数位,则在差值尾部补上被除数的下一位,跳到第2步。否则运算结束,得到的最后差,即为余数。



这个算法是如何变为直接实现算法呢?

其实不难看出,在上述算法中,第2步中的判断就是关键。我们知道一个好的poly的首位肯定是1。所以要看是否执行异或操作,全看当前与poly对齐时,被除数的最高位是否是1。是1则相异或,0则不异或。

那么为什么poly比寄存器要宽1位呢?在长除法的例子中,可以看到与poly对齐时,除数最高位无论是0,还是1,在下次运算中,它都会被抛弃,因为如果1,它与poly相异或得到的是0,如果是0,则与全0异或时得到的还是0。也就是说,无论什么情况下,它都会变成0。



香农-布朗信息论告诉我们,一个事件的信息量与它发生的概率的对数值成反比,即越可能发生的事情其信息量就越小,必然发生的事情,其信息量就是0了。没有信息量,在信息时代就没有用处了。没有用处,就不需要留下它了。

第9节中提到的两个基础理论,应该很容易理解。我关注的是如何把它们过渡到表驱动实现。

表驱动中,信息的处理单元是字节。直接实现中处理的信息单元是位。

由于我们关心的是最后余数,也就是信息处理完成后,留在寄存器里的值。中间过程中会发生什么,中间寄存器的值会变成什么,我们并不关心,只要它的值可以传递到最后,参与最后一次异或运算即可。如果没有这个作为跳板,很难明白,为什么可以把位单元操作,变换为字节单元的操作。按照这个目的作为指引。我们看下,结构长除法的例子,看下在运算过程中到底发生了什么。

例子中,除数的位宽为5。那么来看下前5次运算。用R代表寄存器,p代表除数。

R ^ p ^ (p >> 1) ^ 0 ^ 0

得到的余数是01011。没错这就是我们关心的,前5次运算后,寄存器中的值,正是它将直接参与到下个字节中的运算中。

按照前面提到的第2个基础,这5次运算可以看作是如下,方便后面引用写作R ^ X:

R ^ (p ^ (p >> 1) ^ 0 ^ 0) = R ^ X

OK,这里就可以看出为什么这5次运算可以合并为1次 。首先R中的值只会有2^5种可能,也就是0到31。这个情况是可以提前知道的,也是必然的。由于p是提前也知道的,那么与每一个R值对应的前5次的运算是确切可以知道的,也就是X的值是可以提前知道的。X的值就是我们要在表格里索引的值。也就实现了一次处理5个位的信息了。

前5个位处理完成后,X与其后信息组成一个新的信息列,重复取前5个来索引得到后面的新余数,最终完成整个表驱动算法。

看到这里,相信每个人都已经明白了。:-)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  CRC 注解 表驱动