【计组笔记-2】保姆级分析奇偶校验,海明校验,循环冗余校验

【计组笔记-2】保姆级分析奇偶校验,海明校验,循环冗余校验

1.发生错误

数据在传输过程中发生跳变,导致一个或若干位的数据由1变成0,或由0变成1。

2.发现错误

2.1 校验码

校验码的引入,可辅助校验的进行,例如,规定一组二进制数按从左至右的顺序进行同或运算,得到的值作为校验码添加在最高位,并将添加了校验码的信息进行传输,接收端接收到数据后,可通过一样的同或运算,得到结果后,与最高位的值进行对比,如果相同,则可以认为信息无误,如果不同,则认为信息传输过程中发生了错误。

2.2 合法状态与非法状态

根据2.1所述的例子,可知,若原始数据由3个bit组成,则加上校验码后的合法状态有以下几种:0000,1001,0011,1010,1100,1111,0101,0110,而4位共有16种可能,因此另外8种都是非法状态。

通过观察,可以发现,任意两个合法状态间,最少也有2位数值不同,例如0000与0101差两位才相等。在这种情况下,发送端发送合法状态时,发生任意一位跳变,接收端都可以识别出错误,因为只发生一位跳变是无法出现另一种合法状态的,两个合法状态最少也差着两位。

2.3 码距

2.2小节中所说的,两个正确合法状态间相差的最少位数,即为码距。

码距的定义为,一种编码方案中,各合法码字间的最小距离。其中,若干位代码组成的一个字叫做码字,距离即为两个码字间不同的位数。

由2.2小节可知,理论上讲,码距越大,该种校验方式识别错误的能力越强,而码距为1时,是不具备检错能力的,因为任意跳变一位或若干位,都可获得另一个合法码字。

3.三种校验方式

3.1 奇偶校验码

3.1 奇偶校验定义

奇校验就是码字中1的个数为奇数,偶校验则相反,注意,这里是加上校验码后算的个数,例如原始数据是0101,在奇校验的情况下,为了保证添加完校验码后数据中1的个数是奇数,则校验码为1,处理后的数据应是10101。

3.2 异或一定可以计算偶校验码

实际上,2.1中举的例子就是一种偶校验,但是呢!与例中用同或计算想法,其实偶校验正确的计算方法是异或,具体分析下:在偶校验中,去掉校验码后,剩下的原数据中,若1的数量是奇数,则按位异或后值一定是1,若1的数量是偶数,则按位异或后值一定是0,无论位数是多少都成立,可见偶校验码一定可以通过异或来计算。

但是,若要通过同或来计算偶校验码,则只有在原数据的位数是奇数时才可以,因为,在原数据的位数是奇数时若1为偶数个:偶数个的1同或后是1,剩余奇数个的0同或后是0,0跟1再同或得0。若1为奇数个:奇数个的1同或后是0,剩余奇数个的0同或后是0,0跟0再同或得1。

可见,在上述情况下(即去掉校验码后原数据的位数是奇数),通过同或计算刚好可以得到偶校验码。这也是2.1中用同或计算可以正确进行偶校验的原因。但通过上述分析可知,实际上偶校验用异或运算较为合理

3.3 同或某些情况下可以计算奇校验码

根据3.2的分析可知,在原数据位数是奇数时,同或与异或计算都可以得到偶校验码,反过来说,在原数据位数是偶数时,同或计算得到的就是奇校验码了。但显然这只符合原数据位数是奇数的情况,若为偶数,则只需进行同或或异或计算得到偶校验码后,再与1进行异或,或与0进行同或就可以得到奇校验码了。

综上,还是偶校验码在计算机内部计算起来方便简单些,海明码基于偶校验,想必也有这个因素吧。

3.2 海明校验码

3.2.1 海明校验码的用意

奇偶校验码只有1位,也就是0和1两个状态,俩状态只能有一种表示真,另一种表示假(计算出0则0是真,计算出1则1是真),显然,一位校验码只能判断数据是否有错误,而无法识别错误的具体位置。海明码就基于该问题进行了优化。

3.2.2 海明校验码的位数

具体分析下,若要通过校验码的不同状态指示某个位置出错,则校验码需要多少位呢?显然,这可以通过可能会出错的位数来计算得出。举例说明,若原数据是n位,加上m位海明码后是n+m位,一个状态代表一个位置出错,那么需要n+m个状态,再加一个状态表示所有位置都没出错,则需要n+m+1个状态。

也就是,m位海明码需要最少表示出n+m+1个状态才能满足需求,而m位海明码能够表现的状态是2的m次方,也就是说,2^m>=n+m+1,代入原数据的位数n后,即可求出m。

其实这里有个大bug,细心的应该能看出来,在设计这种可纠错的校验码时,我们期待的是校验码的一种状态可直接表示某一个位置出错,那如果两个位置出错呢?盲生你发现了华点,海明码无法对2个出错位置进行纠错

3.2.3 海明码的纠错原理分析

先跳过上面这个bug不谈,继续往下分析,现在能够理解与计算海明校验码的位数了,那么如何使用呢?分析一下,奇偶校验码可表示原数据整体的正确性,而若干位海明校验码,则可分开表示若干个数据片段的正确性。

与奇偶校验码相似的是,在接收端,如果一个片段(包括对应的校验码)按位异或后,得到的结果是1,则说明片段内存在传输错误,这个错误可能出现在校验位上,也可能出现在原数据中的某一位上(海明码只考虑一位纠错)。在奇偶校验中,只进行检错,因此无需分辨错误具体出现的位置,而在海明码中则要进行分辨

继续分析,如果错误出现在某位校验码处,则每个组与对应校验码按位异或后,只会有一组的结果是1(只考虑一位纠错嘛,不考虑两位校验码同时出错),因此,若校验码为3位,则某位校验码出错的状态应包含以下三种:100,010,001。

而剩余的状态,即有2组及2组以上的异或结果是1,则表示错误出现在出错的小组所包含的原数据中。并且,可以认为,是这几个片段中共同拥有的那一位出错。可见,如果要达到这个目的,原数据中的每一个位置,在所有分组中,至少要出现两次,否则会与一位校验码出错进行混淆,无法分辨。

以上就是海明码纠错过程的分析,即海明码如何确定错误出现的具体位置。

3.2.4 如何确定每个分组的位数

例如,原数据由ABCD四位组成,经计算可知海明码位数为3,用xyz表示,而4位的原数据,若每一位至少出现两次,则至少需要4x2=8个位置,三位海明码可将原数据分为三组,而这3组最少要有8个位置,因此,每组是3个数。

3.2.5 如何确定每个分组中的内容

那么如何确定每组由哪几位组成呢?先来随便划分三个组试试,如:ABC,ACD,BCD。加上海明码后,以xABC,yACD,zBCD这三组举例,A出错,则接收端对三组分别进行异或后,得到的结果是110(6),B出错的结果是101(5),C出错的结果是111(7),D出错的结果是011(3),加上x,y,z出错的结果100(4),010(2),001(1),以及正确的状态000(0)。

如果按照状态值从小到大的顺序进行排列,则如下所示:传输正确,z错,y错,D错,x错,B错,A错,C错。可见随便分组得到的状态是完全没有章法的。

理想状态下,我们希望可以通过海明码转换出10进制数,进而直接确定状态的意义,那么就需要提前设定一个状态与意义的对照表供查阅,具体分析下:首先,能够直接确定的是xyz在表中的下标,因为xyz的出错状态是确定的(即只有1位是1),以3位海明码xyz为例,x出错的下标是4(100),y是2(010),z应是1(001),剩余下标中,0是正确传输(000),而不确定下标的为原数据的ABCD四位,为简单起见,将其顺序填充在3,5,6,7四个位置。综上,这张3位海明码的状态对应表应如下所示:

0 (000)1 (001)2 (010)3 (011)4 (100)5 (101)6 (110)7 (111)
全部正确z错y错A错x错B错C错D错

由于这张供对比的表是人为定义的,因此,除了能直接确定下标的xyz和传输正确外,ABCD按逆序填充也是可以的。这里按顺序为例。

那么如何针对这个表,对原数据进行分组呢?首先明确一点,x,y,z对应海明码的从左至右,也就是100中的1对应的是x。然后继续分析,表中A错是011,也就是A会导致y和z对应的两个组出错,那么y和z中应该有A,而x中没有A。以此类推,y中没有B,z中没有C。

很显然,分组应为,x:BCD,y:ACD,z:ABD。

3.2.6 如何计算海明码,以及确定海明码的码距

每个分组按位异或,得到的就是该组对应的那一位海明码的值,也就是说,其实单看一组的话,跟偶校验是一样的。

关于海明码的码距:想象一下,只跳变一位的话,是肯定无法得到合法状态的,跳变的是校验码位,则与对应分组异或后是1,会被检验出错,若跳变的是原数据位,则在该位的影响下,至少有2组异或结果是1,也会被检验出错。

跳变2位的话,有以下3种情况:2位都是原数据,2位都是校验码,1位是原数据1位是校验码。分开来说这三种情况,当2位都是原数据时,只有在这两位同时出现在一组内,且这两位不会单独出现在其他小组,才不会被检验出错误,试一下可知这是不可能出现的。

当2位都是校验码时,由于校验码对应的小组内数据未发生变化,因此与对应的校验码进行异或得1,会被检验出错误。

当1位是原数据,1位是校验码时,只有在校验码与原数据仅同时出现在一组内时,才不会被检验出错误(即状态合法),但是,上面已经分析过了,原数据的一位最少在所有组内出现2次,因此该情况还是会被检验出错误。

综上,跳变2位依然会被检验出错误,即跳变2位,无法得到新的合法状态。

跳变3位的话,就可能出现合法状态了,举一个例子,如跳变2位校验码,1位原数据,则当原数据所在的小组刚好是跳变的2位校验码对应的小组时,会得到新的合法状态,即无法被检验出错误。

也即,两个合法状态间,最少差距是3位,因此,海明码的码距是3。

3.2.7 海明码的检错与纠错能力

在码距是3的情况下,跳变2位是能被检验出来的,因此检错能力是2,而我们在设计海明码的时候,就只设计了1位的纠错能力,因此纠错能力是1。

首先要明确一点,检错是通过每一组(加上对应的那一位校验码)异或后,得1即为传输出错。此外,要特别注意的是,2位的检错能力和1位的纠错能力实际上是冲突的,因为,虽然跳变2位也能识别出有错(即异或某出现1,而不是000),但是,根据异或后得到的值是无法确定错误的那两个位置的,反而会误判错误来自一个位置,也就是说,虽然检错能力是2,但纠错能力是1还是限制了检验效果。

补充一句:以上分析都是基于顺序填表(上文中的“状态对应表”)的,如果是做题的话,可能会出现逆序的表格,但区别不大,原理相同。

3.3 循环冗余校验码(CRC)

3.3.1 CRC校验简介

海明码实际上是奇偶校验码的一种扩充,而循环冗余校验则完全跳出了奇偶校验的形式,转为使用数学运算来判断数据是否发生了变化,并且,它一样拥有检错与纠错能力。

此外,CRC还对海明码的一些问题进行了优化,例如,海明码的校验码位数是经过计算得出的,原数据位数越长,校验码的位数也不得不越长,且它的检错能力只有3,校验码变长也无法提升检错能力。而CRC在使得校验码长度灵活可控(校验码的位数是除数的二进制位数-1,而除数是人为定义的)的同时,校验码取的越长,检错能力也会相应提升,这个效果就理想了很多。

CRC的大体设计思路是这样的:发送端与接收端共同约定一个除数,在发送端,原数据+校验码与该数据相除后得到的结果是0,因此,在接收端,如果相除后发现结果不是0,则可认为数据发生了变化。

当然,这种方法还是有bug的啦,如果数据跳变到刚好可以被整除,也就是跳变到刚好获取了另一个合法状态,那也一样是无法检错的。但它的检错能力相比海明码更上一层楼,已经是好了很多了,后面再讨论它的检错与纠错能力。

3.3.2 除数

除数是提前约定好的,一般会通过生成多项式的方式给出,如:g(x)=x3+x2+x,提出每一项的系数,组合在一起为1110,把这个二进制数转为10进制,刚好是g(2)的值,这个数就是约定好的除数。

接收方接收到一条信息后,将它与这个约定好的除数进行模2除运算,得到的结果如果不是0,则会认为传输出错。这里贴下模2运算的百度百科模2运算,其实就是专门定义给二进制的加减乘除运算。

3.3.3 补充:关于模2运算的探讨

在学习过程中,发现很多人包括我都有同一个疑惑,模2运算叫运算吗?毕竟它不进位也不借位,转换后也显然不符合十进制的加减乘除运算,这里我有一个初步的思考啊,它是一种人为定义的四则运算,起打辅助的作用(就像线代),而不是十进制那样用于计数的运算。

并且,模2加和减得到的结果跟异或都是完全一样的,其实就是异或,比较特别的可能就是模2乘和模2除,其中模2乘是都为1时才为1,就像if(A且B)只有在A和B都为真时才为真一样,而模2除可以用在求CRC(循环冗余校验码)上。

因此,我觉得,模2运算就是把一些二进制常见的运算形式统一成了一种另类的四则运算,方便在某些情况下作为一种形式统一的辅助工具进行使用而已,仅供参考。

3.3.4 补充:为什么校验码的位数是除数的位数-1

这里稍微解释一下原因,因为后面计算校验码时会直接用这个结论,不解释一下可能会留有疑问。

一句话解释:因为模2除余数最大就是除数的位数-1,下面是详细解释。

首先用百度百科的一个模2除的图举例讲下模2除:
在这里插入图片描述
这个计算过程是这样的:

(1) 在被除数的第4(除数的位数)个位置上面填1,在1111下面写1101(除数),因为一个二进制数最高位肯定是1,那只要被除数位数≥除数,结果的第一位写的就是1。

(2) 1111与1101进行模2减(就像十进制除法里也有减这个过程一样),结果是10,10不足1101,因此从除数剩余的000里拿一个0下来,100还是不够4位,因此结果的第二位填0。

(3) 因为步骤(2)里拿一个0不够,所以再拿一个0下来,变成1000,在模2除里,只要最高位是1,位数≥除数,那就视为够除,因此结果的第三位填1,在1000下面写1101,模2减后得余数是101。

(4) 此时被除数还剩一位,把这一位0拿下来得1010,4位且首位是1,因此结果的第四位填1,且模2减后余数是111。

在知道啥叫模2除以后,分析一下可知,如果希望通过某种处理后模2除可以除尽没有余数,则应该把余数给原数据模2加上(这里有点像十进制,但这个加是模2加),如上图结果是111,只要把原数据最后3位模2加上111即可。

然而,我们不希望改变原数据,所以不可能直接把余数模2加给原数据,而是希望在添加校验码后,使得整个数都可以被整除,前面那一节原数据还能保住。

而我们又希望增加的冗余校验码不要太长,因此,在这种情况下,最少要添加的位数,就是除数的位数-1,因为余数最大就是除数的位数-1,不可能再大了,再大就又可以被整除一次给结果添个1了。因此,被除数模2余数后最多会使得被除数最右边的“除数的位数-1”位发生变化(模2运算不进位,所以最多只会改变加数个位置的值),而我们不希望原数据发生变化,所以要在右侧先加上“除数的位数-1”位,这样变化就不会发生到原数据,只会在加上的位数里有变化(也可能没有变化),而又可以满足处理后的数可以被整除。

这里是我自己的理解,表述能力有限,仅供参考。

3.3.5 计算CRC校验码

校验码的位数是生成多项式最高次幂那一项的幂数,也就是除数的位数-1,举例,若除数为1101,则校验码位数是3。

校验码计算方法为,在原数据右侧添n个零后与除数进行模2除运算,其中n为校验码位数。进行模2除后,用得到余数替换添加的n个零,即可得到CRC校验码(注意,若余数是10,校验码位数是4,则要添加0010凑齐4位)。

通过3.3.4的分析后,其实这个“替换”的过程,也可以理解为,是将被除数与余数相模2加,而由于最后几位是人工添加的一串零,所以直接说是用余数“替换”最后几位也是一样的。

3.3.6 检错与纠错能力

检错:接收方把接收到的带着校验码的数据与约定好的除数进行模2除运算,余数不是0则认为原数据传输过程中出现跳变。

纠错:与海明码类似,也是通过接收端在检错时计算出的结果为引导,来确定错误位置。但是CRC不是一定拥有纠错能力的,具体分析如下:

一串数据发生一位跳变,从结果上看等价于原数据与某数进行异或(模2加),例如1001变成1101,类似于1001与0100进行模2加运算,而所加的数为1的那个位置,就是跳变的位置。

而接收方模2除的余数,其实就是这个模2加的数与除数进行模2除运算的余数。例如,若原数据1001与某除数相除结果为0,跳变后1101与同样的除数相除有了余数,那么,这个余数跟0100与该除数相除的结果是一样的。

通过上面的分析可知,在除数确定的情况下,我们其实可以直接计算出某个位置发生跳变时,接收方所计算得出的余数的值,而在CRC校验过程中,除数是实现约定好的,因此,我们就能够提前拥有一个对照表来获取接收方计算出的余数所对应的错误位置。

然而,由于CRC的除数是自由定义的,因此接收方得到的余数的位数也是自由定义的(除数位数-1),因此,能够唯一表示的错误位置是有限的!例如,如果余数是3位,那么3个位置最多能表示23=8个状态,去掉000表示传输正确,那就只剩下了7个状态可用于表示错误。

在这种情况下,如果原数据(加上校验码后的)长度大于7,那么,从第8个位置开始,如果发生跳变,则余数就会开始重复,如,第1个位置跳变时余数是001,第8个位置发生跳变,余数将又变成001。

并且,余数是循环的,也就是1-7位跳变的余数,与8-14的余数是一一对等的,这也就是循环冗余校验码中,循环的含义。

可见,当原数据太长时,有限的状态将无法与错误类型一一对应,在这种情况下,显然也就失去了纠错能力

因此,如果希望CRC有1位纠错能力,则校验码的位数还是需要按照海明码那样去计算,也即要求验证码的状态数量能够涵盖正确状态,和加上校验码后的每一个位置跳变的状态。

然而,由于该种校验方式并不严格限制校验码的位数,使得较短的校验码就可以拥有检错能力,因此,它还是比海明码要灵活一点

通常情况下,使用起来只要求CRC有检错能力,并不要求它有纠错能力,而它的检错能力是十分强大的,且可以随着校验码长度的增长而增加,用十进制来对比的话,可以这样理解,如果除数是2,则原数据8变成9会被检测出错,变成10就又整除了,但如果除数是5,则原数据10要一直变成15,才能又一次整除。

此外,CRC的检错特性如下所示:
在这里插入图片描述
可见,它的检错能力是十分强大的。

4. 写在最后

这篇只分析了3种校验码,可以看出一种比一种有所进步,但直至CRC校验,还是有漏洞在里面(除非校验位跟原数据一样长,否则无法完美的检测所有可能的错误),除此三种之外还有许多其余的校验方式,由于我也没有学到那么远,因此不知道现在是否拥有了完美的校验方法,这里抛砖引玉,感兴趣的可以自己再深入学习一下其他方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值