首先说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校验算法的纠错方式了
严格的证明就不写了。很难解决文本的格式问题,好难写。