引言

本帅最近在考研,看到408的计组时,发现汉明校验码很是神奇,它是如何找到并能纠正错误的呢?经过大量的面向csdn,终于窥得一星半点汉明大大的些许风采,下面就跟着本帅比一块探索汉明大大的风采吧!!

校验码

说起校验码,先得说说什么是校验码,找错和纠错的原理是什么?
其实不用背那么多定义,只需要知道以下即可:

码距

码距就是一段二进制代码中相同位置的数字不同的个数
例如 : 00 01 有一位不同,码距为1
再如: 00 11 有两位不同,码距为2
那么对于我们来说,传输这两个不同的二进制串哪个更容易发现错误呢?
显然是第二个,因为如果00 第二位数据出错变成01,那么就能立马发现,因为 01 是第二个中所没有的,而第一个中缺有。
基于这样的思想,我们不由得想,如何将第一例中的码距变大呢,并且能发现传输过程中的错误呢?

这就是奇偶校验码要解决的问题。

奇偶校验码

上述第一例中,由于码距是1,不太好判别错误与否,于是我们可以人为的在最左位加上一位使得码距变大。
比如:(1)00 (0)01 这样一变,则码距立马从1变为了2,同时这样每个串中的1的个数为奇数个,我们检测的时候只需要检测串中的1的个数是不是变化了即可。

这样使得一个二进制串中的1的个数为奇数个的校验称为奇校验,同理,在最左边加上一位,使得二进制串中的1的个数为偶数个的校验称为偶校验。

那么,问题来了,知道了如何检验错误,那么偶数个1和奇数个1该如何判别呢?
这就要用到计算机中的一个异或运算。

异或运算

异或运算其实质是不进位的加法(也即模运算),我们通常算加法时会封k进制就进一,这个异或运算其实就是不进位的加法,也即:相同为0,不同为1。
这样我们通过一串二进制中的每位的异或运算就能得知1的奇数和偶数个变化了没有。

这也引出了奇偶校验法的局限性。

奇偶校验码的局限性

1.奇偶校验码由于只能通过异或运算量来检测二进制代码串中奇数个和偶数个1发生的变化,那么当同时有偶数个位置的数字发生变化时,奇偶校验码就失效了。 
2.奇偶检验码只能得知一串校验码中有错误发生,却缺乏定位错误位置的方法。 

总的来说,奇偶校验码只能发现一位出错,既不能定位到错误的位置,也不能纠错,也不能发现多位出错。

此时,我们的汉明大大发现了这个局限性,为了改善对错误不能纠正的局限性发明了汉明校验码。

汉明校验码

首先,因为二进制只有0和1 两个状态,于是我们要想改错,只需要定位到某个位置出错,将这个位置的数字取反即可。

那么我们该如何找到错误的位置呢?

首先我们来考虑一下这么一个问题:

我们的地球是如何精准的定位到每一个城市的呢?
相信各位大大们都能够给出回答,通过经度和纬度啊。
没错就是通过经度和纬度,我们将地球分为了两个分组,横着的纬度和竖着的经度,这样只需要知道经度在哪根上,维度在哪根上就能定位到唯一的位置。

同样还是一个弱智的问题,老师发现你在底下搞小动作,又不认识你的时候,是如何叫你起来回答问题的呢?
这个老师一定会说,那个第几排第几列的同学你站起来回答一下这个问题!
注意,这里老师自动将你分了两组,然后利用排列两组的交集定位到了你。(翻译一下就是,第几排里有你,第几列里有你,两者的交集,产生了你的位置)

很多小伙伴懵逼了,你给我提这个干嘛!没错,我想说的是汉明校验码也是如此。

假如我们从左边第一位开始算起,且位置算作1,那么我们只需要将位置进行分组,就能通过各组的交集找到唯一确定的位置。(翻译一下就是,我们需要知道如何分组,可以通过这组里有二进制数出错,那组中有二进制数出错,从而通过各个组的交集找到唯一出错的位置)

那么,至此,问题就变成了,我们该如何分组使得分组之间能唯一定位到哪位出错,又如何对每个分组组成的二进制字符串进行检测有无错误呢?

第二个问题很好解决,我们只需要对每个分组组成的二进制字符串进行一个奇偶校验即可知道各个分组之间的有无错误情况

那第一个问题呢?

假设我们考虑一个二进制数的纠错问题。

1010110这个二进制数的纠错问题

位置 1 2 3 4 5 6 7
内容 1 0 1 0 1 1 0

我们要找到是具体哪个位置出现了错误。
嗯这样看,好像无法通过对1~7个位置进行分组定位到具体某个位置,但我们不要忘了计算机中存储数据是二进制的,那我们将位置转成二进制看看。

位置 001 010 011 100 101 110 111
内容 1 0 1 0 1 1 0

这样便将位置转换成了二进制表示的,那么这样表示有什么好处呢?
我们发现,每一个进位上只有0和1两个数两种状态,比如011这个位置,个位是1,十位是1,百位是0,这样就是一个天生的分组,我们可以把进位数上的1表示出现错误的分组,0表示未出现错误的分组。

这样的话,以011为例,这个表示的就是百位这个分组里没有出现错误,十位这个分组里出现错误,个位这个分组里出现错误。

既然我们已经知道了该如何分组可以唯一定位到一个具体的位置,那么接下来就是对校验的结果和具体出错位置之间关联一个映射关系。

我们知道校验需要采用奇偶校验法,奇偶校验法需要在每个分组最左边加上一个检验位,
因此在本例中,有7位数,按照位置分组也需要分至少3组,而3组每组前都需要添加一位校验码,此校验码也算进最新的二进制串中,因此,至少需要分4组,每组在最左边添加一个校验码位置Xi,如下:

位置 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011
内容 x1 x2 1 x3 0 1 0 x4 1 1 0
第一组(二进制个位分组位置,个位是1),形如:xxx1 0001 0011 0101 0111 1001 1011
第一组(二进制个位分组)内容 x1 1 0 0 1 0
第二组(二进制十位分组位置,十位是1),形如:xx1x 0010 0011 0110 0111 1010 1011
第一组(二进制十位分组)内容 x2 1 1 0 1 0
第三组(二进制百位分组位置,百位是1),形如:x1xx 0100 0101 0110 0111
第一组(二进制个位分组)内容 x3 0 1 0
第四组(二进制千位分组位置,千位是1),形如:1xxx 1000 1001 1010 1011
第一组(二进制个位分组)内容 x4 1 1 0

然后我们选择偶检验码,并进行异或运算,算出xi的值

可以得到x2 ^ 1 ^ 1 ^ 0 ^ 1 ^ 0 = 0 得到x2=1

同理可得x1 = 0, x3 = 1, x4 = 0。

至此我们就可以得到具体的汉明校验码了,为

位置 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011
内容 0 1 1 1 0 1 0 0 1 1 0

且如果某个位置上发生错误,由于采用的是偶校验,因此分组得到的结果就是1,表示该分组中有错误,
根据二进制的个十百千位置分组可以将错误的分组取交集,确定唯一出错的位置。

校验

例:

假设位置为1011的数据由0变成了1,校验过程为:

按照分组1011分别是(二进制个位出错、十位出错、百位未出错、千位出错)第一组出错、第二组出错、第四组出错

则:第一、二、三、四组分别是按照二进制的个十百千分组,则结果为1011,正好与我们出错的位置相吻合(这也解释了为什么要用偶校验,偶校验出错后各分组都有1出现,正好表示了出错的位置)

校验总结:

奇偶校验

奇偶校验在最左边添校验位,只能校验奇数个出错,不能纠错和找具体出错位置

汉明校验

汉明校验是按照二进制的个十百千进位进行分组,分别采用偶校验(原理都在上文了哟)来校验,由于偶校验的需要,需要在2^k位置处添加校验码。(0001、0010、0100、1000处),同时,添加进的校验码也需要算进新的二进制序列中

假设数据有n位,校验码有x位。则校验码一共有2x种取值方式。其中需要一种取值方式表示数据正确(偶校验全是0表示数据正确),剩下2x-1种取值方式表示有一位数据出错(只能找出一位数据的错误)。因为编码后的二进制串有n+x位,因此x应该满足:2x−1≥n+x

至此,分组找位置以及奇偶校验出错之间的映射关系也找到了,本帅的理解到此结束,欢迎交流斧正

发布评论

分享到:

IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

编程的思想和计算机的逻辑来历讲解
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。