汉明码(Hamming Code),是在电信领域的一种线性调试码,以发明者理查德·卫斯里·汉明的名字命名。汉明码在传输的消息流中插入验证码,当计算机存储或移动数据时,可能会产生数据位错误,以侦测并更正单一比特错误。由于汉明编码简单,它们被广泛应用于内存(RAM)。
历史
人们在汉明码出现之前使用过多种检查错误的编码方式,但是没有一个可以在和汉明码在相同空间消耗的情况下,得到相等的效果。
1940年,汉明于贝尔实验室(Bell Labs)工作,运用贝尔模型V(Bell Model V)电脑,一个周期时间在几秒钟内的机电继电器机器。输入端是依靠打孔卡(Punched Card),这不免有些读取错误。在平日,特殊代码将发现错误并闪灯(flash lights),使得操作者能够纠正这个错误。在周末和下班期间,在没有操作者的情况下,机器只会简单地转移到下一个工作。汉明在周末工作,他对于不可靠的读卡机发生错误后,总是必须重新开始项目变得愈来愈沮丧。在接下来的几年中,他为了解决调试的问题,开发了功能日益强大的调试算法。在1950年,他发表了今日所称的汉明码。现在汉明码有着广泛的应用。
校验
与其他的错误校验码类似,汉明码也利用了
奇偶校验位的概念,通过在
数据位后面增加一些比特,可以验证数据的有效性。利用一个以上的校验位,汉明码不仅可以验证数据是否有效,还能在数据出错的情况下指明错误位置。
纠错
在接收端通过纠错
译码自动纠正传输中的差错来实现码纠错功能,称为
前向纠错FEC。在
数据链路中存在大量噪音时,FEC可以增加数据
吞吐量。通过在传输码列中加入
冗余位(也称纠错位)可以实现
前向纠错。但这种方法比简单重传协议的成本要高。汉明码利用奇偶块机制降低了
前向纠错的成本。
校验方法
如果一条信息中包含更多用于纠错的位,且通过妥善安排这些纠错位使得不同的出错位产生不同的错误结果,那么我们就可以找出出错位了。在一个7位的信息中,单个位出错有7种可能,因此3个错误控制位就足以确定是否出错及哪一位出错了。
汉明码SECDED(single error correction, double error detection)版本另外加入一检测比特,可以侦测两个或以下同时发生的比特错误,并能够更正单一比特的错误。因此,当发送端与接收端的比特样式的汉明距离(Hamming distance)小于或等于1时(仅有1 bit发生错误),可实现可靠的通信。相对的,简单的奇偶检验码除了不能纠正错误之外,也只能侦测出奇数个的错误。
下列通用算法可以为任意位数字产生一个可以纠错一位的汉明码:
1.从1开始给数字的数据位(从左向右)标上序号, 1,2,3,4,5...
2.将这些数据位的位置序号转换为二进制,1, 10, 11, 100, 101,等。
3.数据位的位置序号中所有为二的幂次方的位(编号1,2,4,8,等,即数据位位置序号的二进制表示中只有一个1)是校验位
4.所有其它位置的数据位(数据位位置序号的二进制表示中至少2个是1)是数据位
5.每一位的数据包含在特定的两个或两个以上的校验位中,这些校验位取决于这些数据位的位置数值的二进制表示
(1) 校验位1覆盖了所有数据位位置序号的二进制表示倒数第一位是1的数据:1(校验位自身,这里都是二进制,下同),11,101,111,1001,等
(2) 校验位2覆盖了所有数据位位置序号的二进制表示倒数第二位是1的数据:10(校验位自身),11,110,111,1010,1011,等
(3) 校验位4覆盖了所有数据位位置序号的二进制表示倒数第三位是1的数据:100(校验位自身),101,110,111,1100,1101,1110,1111,等
(4) 校验位8覆盖了所有数据位位置序号的二进制表示倒数第四位是1的数据:1000(校验位自身),1001,1010,1011,1100,1101,1110,1111,等
(5) 简而言之,所有校验位覆盖了数据位置和该校验位位置的二进制与其值不为0的数。
采用奇校验还是偶校验都是可行的。偶校验从数学的角度看更简单一些,但在实践中并没有区别。校验位一般的规律可以如下表示:
观察上表可发现一个比较直观的规律:第i个检验位是第2^(i-1)位,从该位开始,检验2^(i-1)位,跳过2^(i-1)位……依次类推。例如上表中第3个检验位p4从第2^(3-1)=4位开始,检验4、5、6、7共4位,然后跳过8、9、10、11共4位,再检验12、13、14、15共4位……
编码原理
奇偶校验是一种添加一个奇偶位用来指示之前的数据中包含有奇数还是偶数个1的检验方式。如果在传输的过程中,有奇数个位发生了改变,那么这个错误将被检测出来(注意奇偶位本身也可能改变)。一般来说,如果数据中包含有奇数个1的话,则将奇偶位设定为1;反之,如果数据中有偶数个1的话,则将奇偶位设定为0。换句话说,原始数据和奇偶位组成的新数据中,将总共包含偶数个1. 奇偶校验并不总是有效,如果数据中有偶数个位发生变化,则奇偶位仍将是正确的,因此不能检测出错误。而且,即使奇偶校验检测出了错误,它也不能指出哪一位出现了错误,从而难以进行更正。数据必须整体丢弃并且重新传输。在一个噪音较大的媒介中,成功传输数据可能需要很长时间甚至不可能完成。虽然奇偶校验的效果不佳,但是由于他只需要一位额外的空间开销,因此这是开销最小的检测方式。并且,如果知道了发生错误的位,奇偶校验还可以恢复数据。 如果一条信息中包含更多用于纠错的位,且通过妥善安排这些纠错位使得不同的出错位产生不同的错误结果,那么我们就可以找出出错位了。在一个7位的信息中,单个数据位出错有7种可能,因此3个错误控制位就足以确定是否出错及哪一位出错了。
一般来说,若汉明码长为n,信息位数为k,则监督位数r=n-k。若希望用r个监督位构造出r个监督关系式来指示一位错码的n种可能位置,则要求
2r-1≥n或2r≥k+r+1
现以数据码1101为例说明汉明码编码原理,此时D1=1、D2=1、D3=0、D4=1,在P1编码时,先将D1、D2、D4的二进制码相加,结果为奇数3,校验码P1对奇数结果编码为1,偶数结果为0(偶校验法),因此,
D1+D2+D4=3,P1=1;
D1+D3+D4=2,P2=0;
D2+D3+D4=2,P3=0;
这样,参照上文的位置表(P1 P2 D1 P3 D2 D3 D4),汉明码处理的结果就是:1010101
在这个4位数据码的例子中,我们可以发现每个校验码都是以三个数据码为基准进行编码的。
从编码形式上,我们可以发现汉明码是一个校验很严谨的编码方式。在这个例子中,通过对4个数据位的3个位的3次组合检测来达到具体码位的校验与修正目的(不过只允许一个位出错;大于1且偶数个位出错时,校验反而是正确的,造成误判;大于1且奇数个位出错则无法定位)。在校验时则把每个校验码与各自对应的数据位值相加,如果结果为偶数(纠错代码为0)就是正确,如果为奇数(纠错代码为1)则说明当前汉明码所对应的三个数据位中有错误,此时再通过其他两个校验码各自的运算来确定具体是哪个位出了问题。
还是刚才的1101的例子,正确的编码应该是1010101,对应P1 P2 D1 P3 D2 D3 D4。
如果第五个数据位在传输途中因干扰而变成了0,就成了1010001, 即 D2=0。
检测时:
1)P1=D1 + D2 + D4=1 + 0 + 1=2,除以2余数0,原来第一位纠错代码为1,错误,说明P1 D4 D2 D1中有一位是错误的。
2)P2=D1 + D3 + D4=1 + 0 + 1=2,除以2余数0,正确,说明P2 D4 D3 D1都是正确的,这里结合上边已经可以得出只有P1和D2中一个是错误的。
3)P3=D2 + D3 + D4=0 + 0 + 1 =1,除以2余数1,而原来第三位纠错代码为0,有错误,由上边2)知道D4和D3是正确的,那么这里说明只有P3和D2中一个是错误的。
综合以上,可以得出这个结论:D2出错了。
数量之比
那么汉明码的数量与数据位的数量之间有何比例呢?上面的例子中数据位是4位,加上3位汉明码是7位,而2的3次幂是8。这其中就存在一个规律,即2^P≥P+D+1,其中P代表汉明码的个数,D代表数据位的个数,比如4位数据,加上1就是5,而能大于5的2的幂数就是3(2^3=8,2^2=4)。这样,我们就能算出任何数据位时所需要的汉明码位数:7位数据时需要4位汉明码(16>4+7+1),64位数据时就需要7位汉明码(128>64+7+1),大家可以依此推算。此时,它们的编码规也与4位时不一样了。