海明校验码
- 海明码是基于偶校验的一个拓展, 对于n个有效的信息,我们会把它分为k个分组,然后对k的分数分别的进行偶校验
- 也就是说每一个分组会对应一个校验位,最终我们会携带k个校验位, 可以反映更多种状态的信息
- 除了反馈对错之外,我们还可以知道哪一位出了错, 这就是海明码的设计思想
- 基于这个思路,需要探讨几个问题
- 第1个问题,我们需要把这n个信息位分为多少个分组
- 第2个问题这n个信息位,我们怎么把他们分派到各个分组当中
- 第3个问题是基于海明校验码进行检错和纠错
1 ) 需要设置多少个校验位
- 假设信息位(n个) 添加的冗余校验位(k个)
- 我们期待,这k个校验位除了能反映对错之外,还能指明是哪一个比特位出现了错误
- k个比特能表示2的k次方种状态,而海明校验码整体来看,是信息位 + 校验位
- 也就是说, 海明校验码位数 = n + k, 而这n+k位都可能出错
- 那么这2的k次方种状态当中需要包含n+k种情况,那除了出错的这n+k种情况之外,还需要包含一种正确的状态
- 因此我们可以得到这样的一个不等式:
2
k
≥
n
k
1
2^k \geq n + k + 1
2k≥n+k+1, 我们需要通过这个不等式来确定我们需要添加多少个校验位
- 如果有4个信息位,那么我们就只能取k等于3才能满足这个式子:
2
3
≥
4
3
1
2^3 \geq 4 + 3 + 1
23≥4+3+1
- 下面这个表给出了n和k的一般对应关系,可记忆,或者自己推
| n | 1 | 2-4 | 5-11 | 12-26 | 25-57 | 58-120 |
|---|---|---|---|---|---|---|
| k | 2 | 3 | 4 | 5 | 6 | 7 |
- 基于上述结论,如果说有4个信息位的话,那么我们可以确定我们要添加的校验位的数量k=3,也就是说最终我们生成的海明校验码应该是4+3=7位
2 ) 如何分组
- 为了区分信息位和校验位, 我们用D1D4来表示这4个信息位,然后用P1P3来表示这三个校验位,用H1~H7来分别对应最终的这7位海明码
- 那这些信息位和校验位应该放到什么位置呢?
- 一个很容易想到的办法是把这三个校验位放到头部的位置,然后把4个信息位放到尾部的位置
- 但是海明码不能这么做,有一些特殊的规定,在海明校验码中规定所有的校验位
P
i
P_i
Pi应该分别放在
2
i
−
1
2^{i - 1}
2i−1这些位置上
- 也就是说P1P2P3,这几个校验位,应该分别把他们放到: 第1、2、4这几个位置,那如果还有一个校验位P4的话,那显然应该放到第8的位置
- 规律是:和我们二进制的权值的上升关系是相符合的, 比如:1、2、4、8、16
- 所以我们可以把这些校验位所放的位置, 看作是这个校验位它所对应的某一种权值
- 总之, P1放到第1个位置,然后P2放到第2个位置,P3要放到第4个位置,剩下位置存放其他的信息位, 如下表所示
| H7 | H6 | H5 | H4 | H3 | H2 | H1 |
|---|---|---|---|---|---|---|
| D4 | D3 | D2 | P3 | D1 | P2 | P1 |
| 1 | 0 | 1 | 0 |
- 目前为止我们已经确定了,基于上述的例子,我们需要添加三个校验位
- 或者换一个角度来说,需要把这些信息被分为三个分组,每个分组分别进行偶校验
- 因此接下来我们应该确定一种规则,就是三个分组当中应该分别包含哪几个信息位
- 当我们确定了如何分组之后,那么与这个分组相对应的偶校验位的值就很好确定了
- 来看一下怎么做,需要把这些信息为他所处的位置的序号用二进制的形式表示
- 比如,对于D1这个信息来说,它所处的位置是3, 那么3的二进制表示应该是011, 每个二进制位的权重是1、2、4(从低到高),011的值就是2+1=3
- 而下一个信息位是D2,它所处的位置是5,那么我们用二进制表示应该是101,此时,4+1=5
- 而D3所处的位置是6,那么6用二进制表示应该是110,此时,4+2=6
- 最后是D4,它处于7这个位置,用二进制表示就是111, 此时,4+2+1=7
- P1、P2、P3 分别把它放到1、2、4这些位置,我们可以把它理解为某一种权重,那么这些权重和刚才提到的这三位二进制的权重是一一对应的
- H3: 3 -> 011
- H5: 5 -> 101
- H6: 6 -> 110
- H7: 7 -> 111
- 所以P1这个偶校验位,它所处的分组当中应该有哪些信息位呢?我们只需要把末位为1的这几个信息未把它归为P1所属的分组就可以了
- 也就是如上:H3、H5、H7这几个位置所对应的信息位归为同一个分组,进行偶校验:
P
1
=
H
3
⊕
H
5
⊕
H
7
=
D
1
⊕
D
2
⊕
D
4
=
0
P_1 = H_3 \oplus H_5 \oplus H_7 = D_1 \oplus D_2 \oplus D_4 = 0
P1=H3⊕H5⊕H7=D1⊕D2⊕D4=0
- 只需要把这个组里面的所有信息位进行异或运算,就可以确定我们的P1应该取0还是取1, 这就是P1的一个计算方式
- 接下来第2个分组,我们应该让它包含H3、H6和H7所对应的这几个信息位, 获得偶校验位:
P
2
=
H
3
⊕
H
6
⊕
H
7
=
D
1
⊕
D
3
⊕
D
4
=
1
P_2 = H_3 \oplus H_6 \oplus H_7 = D_1 \oplus D_3 \oplus D_4 = 1
P2=H3⊕H6⊕H7=D1⊕D3⊕D4=1
- 最后一个分组的确定方法也是一样的:H5、H6、H7, 也就是D2、D3、D4,它们从属于同一个分组,把它们异或可以得到偶校验位的值:
P
3
=
H
5
⊕
H
6
⊕
H
7
=
D
2
⊕
D
3
⊕
D
4
=
0
P_3 = H_5 \oplus H_6 \oplus H_7 = D_2 \oplus D_3 \oplus D_4 = 0
P3=H5⊕H6⊕H7=D2⊕D3⊕D4=0, 这时候我们已经全部确定了海明校验码的值
| H7 | H6 | H5 | H4 | H3 | H2 | H1 |
|---|---|---|---|---|---|---|
| D4 | D3 | D2 | P3 | D1 | P2 | P1 |
| 1 | 0 | 1 | 0 | 0 | 1 | 0 |
3 ) 检错和纠错
- 怎么检测出错误呢?其实就是把各个分组内的这些二进制比特币进行一个异或运算, 也就是对这个分组进行偶校验
- 如果说这个分组内没有出错的话,那么进行异或运算得到的结果应该是0
- 如果现在接收方接收到的数据没有发生任何一个比特的错误,即:1010010,我们根据刚才确定的这三个分组对每个分组内的这些比特位依次进行异或运算
- 因为每个分组都有偶数个1,所以异或之后肯定都是000,这是没有出错的情况
- S
1
=
P
1
⊕
D
1
⊕
D
2
⊕
D
4
=
0
⊕
0
⊕
1
⊕
1
=
0
S_1 = P_1 \oplus D_1 \oplus D_2 \oplus D_4 = 0 \oplus 0 \oplus 1 \oplus 1 = 0
S1=P1⊕D1⊕D2⊕D4=0⊕0⊕1⊕1=0
- S
2
=
P
2
⊕
D
1
⊕
D
3
⊕
D
4
=
1
⊕
0
⊕
0
⊕
1
=
0
S_2 = P_2 \oplus D_1 \oplus D_3 \oplus D_4 = 1 \oplus 0 \oplus 0 \oplus 1 = 0
S2=P2⊕D1⊕D3⊕D4=1⊕0⊕0⊕1=0
- S
3
=
P
3
⊕
D
2
⊕
D
3
⊕
D
4
=
0
⊕
1
⊕
0
⊕
1
=
0
S_3 = P_3 \oplus D_2 \oplus D_3 \oplus D_4 = 0 \oplus 1 \oplus 0 \oplus 1 = 0
S3=P3⊕D2⊕D3⊕D4=0⊕1⊕0⊕1=0
- 如果说接收方接收到的数据为:1010000,H2这一位发生了错误,也就是P2这个校验位从1变成了0
- 第1个分组进行异或得到了0,第2个分组中由于P2发生了跳变,所以导致第2个分组中,现在只有奇数为1,那么异或出来的结果就是1
- 而第3个分组没有任何一个数据发生跳变,因此异或的结果应该是0
- S
1
=
P
1
⊕
D
1
⊕
D
2
⊕
D
4
=
0
⊕
0
⊕
1
⊕
1
=
0
S_1 = P_1 \oplus D_1 \oplus D_2 \oplus D_4 = 0 \oplus 0 \oplus 1 \oplus 1 = 0
S1=P1⊕D1⊕D2⊕D4=0⊕0⊕1⊕1=0
- S
2
=
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新