关于Hamming校验纠错算法的证明

首先说Hamming算法是什么。

没有查过原始的文献,所以没见过它原始的定义和证明。依照现在手头上的<<Structure Computer Organization>>一书上的说明。

Hamming算法可以对任意字长的内存建立起纠正码(注意,是不止可以检验出错误,还可以纠错)。原理如下:

假设原始的数据有m位,向这m位数据里加入r位检验位,就得到m+r位的字长。在这m+r位里,所有2的整数幂的位是检验位,其他的是数据位(注意这里的位都是从1开始计数的,而不是从0开始)。

每一个校验位可以检验特定的位。

例如,一个16位的字就需要加入5位的校验位,即第1、2、4、8、16位为校验位。此时的实际字长达到21位。第一个校验位负责检验第1、3、5、7、9、11、13、15、17、19、21位,第二个校验位负责检验第2、3、6、7、10、11、14、15、18、19  ……..

具体如下:

第1位负责检验:1、3、5、7、9、11、13、15、17、19、21

第2位负责检验:2、3、6、7、10、11、14、15、18、19

第4位负责检验:4、5、6、7、12、13、14、15、20、21

第8位负责检验:8、9、10、11、12、13、14、15、

第16位负责检验:16、17、18、19、20、21

那么,怎么知道一个检验位都负责检验哪些位呢?

Hamming校验码的设置原则是:第B位通常由第b1,b2,b3,…,bj位来检验,其中B=b1+b2+b3+…+bj.

比如,第5位由第1位和第4位一起校验(5=1+4),第6位由第2位和第4位一起校验(6=2+4)。

为了说明纠错过程,下面假设有一个这样的16位字:

1 1 1 1 0 0 0 0 1 0 1 0 1 1 1 0

假设使用偶检验,则加入第1、2、4、8、16位校验码后得到的21位字就如下所示:

(偶检验就是,根据数据位1的个数调整检验位,使得总共1的位数为偶数个)

0 0 1 0 1 1 1 0 0 0 0 0 1 0 1 1 0 1 1 1 0

假设第五位出错了,变成:

0 0 1 0 0 1 1 0 0 0 0 0 1 0 1 1 0 1 1 1 0

那么,检验位1和检验位4所在的那个检验列的1的个数都不是偶数个了,所以就知道出错了。

这时,只要知道哪一位出错了就可以将它纠正回来。

想要知道哪一位出错,有两种方法:

第一个是对比分析。比如,上面的例子中,由于第1个检验位和第四个验位所检验的队列都出错了,那么,出错位肯定是他们所共有,而其他队列所没有的。对比一下就知道那就是第5位了。

第二种方法就是,将出错队列的检验位相加,就得到出错位。上面例子中,1+4=5.

需要说明的是,这种算法纠错的前提是,它假设出错的位数为1位。也就是说,如果错了3位,这个算法也会以为它只有一位出错(错了2位就检验不出来了,因为奇偶检验的Hamming码距是2)

我们已经知道这样子可以检错并纠错,但是为什么呢?  如何保证这种算法的正确性?

如果想做证明,首先很自然的一个疑问是:根据Hamming算法设置校验码的原则(即第B位通常由第b1,b2,b3,…,bj位来检验,其中B=b1+b2+b3+…+bj.),如何保证对于码字中的每一位,都存在一些校验位,这些校验位相加得到这个位?比如,用上面的例子,第17位应该由哪些位检验?由于17比较小,我们很容易知道 17=1+16,从而知道应该是由第1和第16位检验。但是Hamming算法是可以检验任意的位数的,如果那个位很大怎么办? 1000?1000000? 1000292? 显然无法全部枚举。

再者,怎么知道根据Hamming算法设置校验位的原则所得到的校验位是唯一的?也就是说,对于上面的17,我们已经知道17=1+16,但是怎么知道不会有其他的17 = m + n ?当然,由于17很小,我们可以枚举完,知道不会有其他可能了,但是如果那个位很大呢?1000?10000000? 1232312312?显然也无法枚举完,必须通过严格的数学证明。

我们首先来证明这两个个问题。证明完了这两个问题,整个证明也就差不多完成了。

证明如下:

首先,Hamming算法设置校验位的原则是:所有的2的整数幂的位都是校验位(也就是第1、2、4、8、16、32….位)。

   很明显的一点是,每一个位数都不会大于那些存在的校验位相加的最大值,比如说,对于上面的例子的21位,即使是最大的21,也不会比1+2+4+8+16大。因为,给定一个数n, 如果 2^r < n < 2^(r+1) (  在这里 16 < 21 <32 ),那么n必然小于2^0 + 2^1 + 2^2 + … + 2^r, 因为这个等比数列之和等于2^(r+1) 减1.而 n < 2^(r+1), 也就是 n <= 2^r-1.

好,在 2^r < n < 2^(r+1) 的假设下 ,再证明一点,即,如果要有一个和式,2^i + 2^j  + …. + 2^k = n, 那么,里面肯定会有2^r,因为,如果没有2^r的话,即使是2^0 , 2^1 , 2^2……2^(r-1) 全加起来也只有2^r – 1 而已(等比数列求和),更不用说n了,因为2^r < n < 2^(r+1). 所以如果要有一个这样的2的整数次幂的和式,它的和为n的话,里面必须要有一个2^r

在上面,我们假设有这样一条式子:

2^i + 2^j + … + 2^r= n

即一些2的整数次幂加起来等于n。也说明了其中一个必须是2^r. 其中2^r < n <2^(r+1)

现在把式子做一下变换,得:

2^i + …+ 2^j = n – 2^r

(形式上来说就是将n换成了 n – 2^r )

现在,令m=n – 2^r

现在我们就变成了证明存在一个2的整数次幂的和式,其和等于m了:

2^i + …+ 2^j = m

由于m=n – 2^r, 而 2^r < n <2^(r+1), 那么可以知道 0 < m < 2^r

而式子左边的 2^i 和 2^j 的范围是 0 ~ 2^(r-1). 所以所以变换之后又回到之前n的情况。所不同的是,n的范围是 2^r < n < 2^(r+1),  而 m的范围是0 < m < 2^r.

但是其实本质没有变。我们依然可以找到一个q, 使得2^q < m < 2^(q+1). 而且这个m依然在那些剩下的2^i….. 2^j 之和的表示范围内,这就回到了和之前的n一模一样的情况了。

所以可以看到,按照这种方式,从n里面不断地减去一个2的次幂,就可以得到一个并且唯一一个和式,使得其和为n

也就是  2^i + 2^j + … + 2^r= n

数学上,这叫数学归纳法 :)

上面我们证明了对于任意一个位 n ,都有且仅有一个和式使得 2^i + 2^j + … + 2^r= n

也就是说,那个位 n 有唯一的检验位 i 和 j 和 … 和 r

那么,当我们发现出错的时候,我们就知道出错的那些队列的检验位 i 和 j 和 … 和 r 相加就得到出错位的位置了(也就是n了)。这也就是Hamming校验算法的纠错方式了

严格的证明就不写了。很难解决文本的格式问题,好难写。

时间: 2024-10-24 11:04:33

关于Hamming校验纠错算法的证明的相关文章

Hamming校验码

可参考:http://winda.blog.51cto.com/55153/1068000 Hamming校验码作用:用于校验通信数据,防止出现错误,并具有一定的纠错功能. 汉明码在传输的消息流中插入验证码,当计算机存储或移动数据时,可能会产生数据位错误,以侦测并更正单一比特错误.由于汉明编码简单,它们被广泛应用于内存(RAM). 1,获取最小校验码位数:对于有n个信息位的信息,需要k个校验位,满足:2^k-1>=n+k;使k最小即可得出n个信息位所需最小的校验码数: 2,确定校验码所在位置:共

扩展欧几里德算法及其证明

扩展欧几里德算法: 已知a, b求解一组x,y,使它们满足等式: ax+by = gcd(a, b) =d(解一定存在,根据数论中的相关定理). 扩展欧几里德常用在求解模线性方程及方程组中. 证明: ax+by=gcd(a,b); 1. (1) a = 0,ax+by = gcd(a,b) = gcd(0,b) = b, 此时x = 0(此时x的值是任意的),y = 1: (2)b = 0, ax + by = gcd(a,b) = gcd(a,0) = a, 此时x = 1,y = 0(此时y

字典序法生成全排列算法的证明

引言 对一个给定数据进行全排列,在各种场合经常会用到.组合数学中,生成全排列的方法有很多,卢开澄老师的<组合数学>中就介绍了三种:序数法,字典序法,临位互换法等.其中以字典序法由于算法简单,并且使用的时候可以依照当前状态获取下一个状态,直到所有排列全部完成,方便在程序中随要随用,应用比较广泛,STL中的Next_permutation也是使用此法. 算法定义 首先看什么叫字典序,顾名思义就是按照字典的顺序(a-z, 1-9).以字典序为基础,我们可以得出任意两个数字串的大小.比如 "

洗牌算法及其证明

问题定义: 给定有序序列1-n,要求将其打乱,使得每个元素在任意位置出现的概率均为1/n. 程序实现: void shuffle(int *arr, int n) // n为序列中元素总数 { int idx; for(int i = 0; i < n; i++) { idx = rand() % (i+1); // idx在下标[0, i]内 swap(&arr[idx], &arr[i]); } } 数学归纳法证明: (1)当n=1时,idx必为0,所以元素arr[0]在任何一个

判断一个正整数是否是2的N次方的简洁算法及其证明

在写代码时遇到了“判断一个正整数是否是2的N次方”的问题,不想调用 java.lang 的 Math 类库进行浮点运算,觉得转换为浮点不是个好办法. 遂在网上搜索了一下,发现有人列出来好几种写法,列举几种: 1.通过循环除2:这种方法不值一提,略过: 2.针对32位/64位只有有限个 2 的N次方的常量值,逐个进行比较:额...这个也略过: 3.通过正则表达式进行文本匹配,判断是否2的后面都是 0 :这个绕得更远了... 最后,有一种最简洁优雅的写法:(value & (value -1)) =

shiro 自定义 密码校验hash算法

Shiro 自定义密码校验: 两步: 1.自定义类MyCredentialsMatcher实现CredentialsMatcher接口 2.实现boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info)方法 第一个参数是登陆的用户 第二个一般是数据库里面的用户( 也就是 protected AuthenticationInfo doGetAuthenticationInfo()方法返回的实体和凭据

传输数据校验算法研究

 今天简单介绍一些传输数据校验的方法,就昨天整理的资料和就我的理解写的Demo做个总结!希望大家多多指教! 定义 通俗的说,就是为保证数据的完整性,用一种指定的算法对原始数据计算出的一个校验值.接收方用同样的算法计算一次校验值,如果和随数据提供的校验值一样,说明数据是完整的. 实际应用 防止自己的程序被篡改. 有些可执行程序,当被改了资源时再运行会有文件已损坏的提示,这就是使用了数据校验.本例是用md5做为数据校验的算法.当然你可以使用个性化的 比如des作为数字签名,那样安全性更高. 校验方法

互联网IP合全局路由优化的原则-Dijkstra算法证明

周末继续写东西的一半填补了,为了达到完美的一天.我们知道一个事实,IP地址太多.统一管理是不可能的了,无论从控制平面从数据/管理层表示,飞机是如此. 所以.IP协议被设计为可伸缩.供IP路由术语,跳路由进行计算.当然,支持"源路由",源路由就是说数据在出发前就已经把路线规划好了,逐跳路由是IP路由的标准形式.也就是说.IP数据包是在路上即时规划路线的.       我比較喜欢IP路由是由于这也是我旅行的方式,我喜欢旅行,可是我不喜欢事先订酒店.事先规划路线.导航等,我的方式是在路上看路

Dijkstra算法原理及证明(转)

Dijkstra算法及其证明 算法: 设G是带权图,图中的顶点多于一个,且所有的权都为正数.本算法确定从顶点S到G中其他各个顶点的距离和最短通路.在本算法中P表示带永久标记的顶点的集合.顶点A的前驱是P中的一个顶点,用来标记A.顶点U和V之间的边的权重用W(U,V)表示,如果U和V之间没有边,则记作W(U,V)=∞. 步骤1 (对S做标记) (a)将S标记为0,并使S没有前驱 (b)令P={S} 步骤2 (对其他顶点作标记) 将每个不在P中的顶点V标记为W(S,V)(可能是暂时的),并使V的前驱