什么是汉明码?
“汉明码”,也称作“海明码”,英文名为“hanming code”,在通信领域中,“汉明码”有广泛的应用,由理查德·卫斯里·汉明于1950年发明。“汉明码”是一种“错误纠正码”,可以用来检测并且纠正数据从发送端发往接收端中发生的错误。
“冗余位”
“冗余位”是一种二进制位,它被用来添加到需要传输的数据信息中,以确保信息在传输过程中不会发生丢失或者改变。
对于“冗余位”究竟需要多少位这个问题,我们有一个公式可以用来计算:
其中,r指的是冗余位究竟需要多少位,而m指的是传输的数据的二进制位数。
假设传输的数据的二进制位数是7位,那么冗余位的个数就可以通过上面的公式来计算:
= 2^4 ≥ 7 + 4 + 1
因此,我们的至少需要4个二进制位作为“冗余位”。
“奇偶校验位”
奇校验位
在奇校验检测方式中,对于需要发送的数据信息比特,检查其中1的个数。如果这串比特中1的个数是奇数,为了保证加上“冗余位“后,””整串数据中1的个数最后为奇数,可想而知,冗余位上应该设置为“0”。如果在没有添加“冗余位”之前,数据比特流中的1的个数为偶数,那么为了最后把1的个数凑成一个奇数,冗余位上应该设置为1.
偶校验位
同理,在偶校验检测方式中,对于需要发送的数据信息比特,仍然检查其中1的个数。如果这串比特中1的个数是奇数,为了保证加上“冗余位“后,””整串数据中1的个数最后为偶数,可想而知,冗余位上应该设置为“1”。如果在没有添加“冗余位”之前,数据比特流中的1的个数为偶数,那么为了最后把1的个数凑成一个偶数,冗余位上应该设置为0.
汉明码的编码方式
汉明码对于初学者来说,可能会让人头大一些。但是,如果你认真阅读并理解了上面讲述的“奇偶校验法”的话,汉明码将会变得非常简单。我们上面讲述了“奇偶校验法”的两个缺点,其中一个是当传输过程中发生了2位或更大的偶数位改变时,奇偶校验法将会变得失效。然而,随着科学技术的飞速发展,如今在数据通信传输过程中,数据发生改变的几率是非常非常的小了,1位数据发生改变的几率更加小,因此,2位即2位以上比特位发生改变的情况我们假设其永远不可能发生。因此,我们剩下来需要解决的问题就是:假设有1位发生改变,有没有什么办法能够让我们发现是哪一位发生了改变呢?如果能找到是哪一位发生了改变,我们就能够纠正它,0变1,1变0。汉明码就很好的解决了这个问题。
首先,让我们来看一下汉明码是如何编码的吧!汉明码其实就是“奇偶校验法”的升级版,它是多个“奇偶校验法”的组合糅合在一起,但是奇偶校验位的位置不一定再是最后一位了,而是有其他的计算方法。
假设我们需要传输的数据信息是由7位二进制位组成,通过第二部分我们已经算出来了至少需要4位冗余位。因此,整个信息流有11个二进制位。其中有7位数据位和4位“奇偶校验位”。
汉明码对于“奇偶校验位”的位置有特殊的规定:
所有2的幂次位(2^0=1,2^1=2,2^2=4,2^3=8……)作为“奇偶校验位”,因此,第1位,第2位,第4位,第8位为奇偶校验位,其他的7位为数据位。
此时,肯定又有同学会犯迷糊了,“奇偶校验位”如果这样安排的话,那哪个奇偶校验位又“管着”哪一组数据呢?
此时,就要讲到汉明码的核心编码方法了,我们把索引的二进制形式表示出来,如下图所示:
我们接下来可以对二进制索引通过一个这样的方法对其分类:
从右往左(低位往高位)数,第一位是“1”的索引有:1011,1001,0111,0101,0011,0001
分别对应的10进制索引为:11,9,7,5,3,1,那么,这几位上面的数据位和1号“奇偶校验位”构成了一组。
同理 第二位是“1”的索引有 0010 0011 0110 0111 1010 1011
分别对应 2 3 6 7 10 11
第三位是1的索引有 0100 0101 0110 0111
分别对应 4 5 6 7
第四位对应的是 8 9 10 11
这样,分组我们就已经确立好了,接下来需要开始填充数据位,假设我们需要传输的7位数据位:1011001
对于第一组来说(1,3,5,7,9,11位为一组):1的个数为4个,偶数个,因此①号应该为1。这样1的个数最后才能保证为奇数。
对于第二组来说(2 3 6 7 10 11为一组)1的个数为3个 奇数个 因此 二号为0
对于第三组来说(4 5 6 7 )为一组 1的个数为1 因此 三号位 0
对于第四组来说 (8 9 10 11)1的个数为2 因此四号位为1
汉明码的“纠错”和“改正”
上面,我们已经完成了“汉明码”的编码,那么,汉明码又是如何发现错误以及改正错误的呢?
假设,第“5”号位上的“0”在传输过程中变成了“1”,接收方收到的数据则为:10111010101。
首先第一组 1的个数为6 不再是奇数个了,因此,我们可以断定,这一组中肯定有某个数据发生了错误,但不能确定是哪一位上发生了错误。为了达到“奇校验”,我们必须补1个1来达到奇数个1。
第二组 1的个数为3个 奇数个 补一个0
第三组 1的个数为2 补一个1
第四最 1的个数为3 补一个0
我们发现,最后得出来的二进制数是:0101,我们会神奇地发现,0101就是10进制5的二进制表现,因此,我们可以准确的知道,5号位上发生了数据的改变,我们只要对5号位进行置反操作即可。最后,接收方就可以修改成为正确的数据啦。