Skip to content

海明码详解

考情分析

海明码是 408 数据表示章节的高频考点,大题和选择题都会出。常考题型:给定数据位求校验位数量、写出各校验位的值、给定接收码判断是否出错并纠正,以及 SEC-DED 方案的判断逻辑。

海明码的核心思想

海明码在数据位之间插入若干校验位,使码距 d=3,从而可以纠正 1 位错误检测 2 位错误

精妙之处在于:每个数据位被分配到多个校验组中,出错时各校验组的结果拼起来直接给出出错位的编号

校验位数量

设数据 k 位,校验位 r 位,总码长 n=k+r。校验位数量满足:

2rk+r+1

+1 是为了表示"无错误"的情况(故障字全 0)。

数据位 k校验位 r总码长 n
123
437
8412
16521
32638
64771

校验位的位置

校验位放在编号为 2i 的位置(i=0,1,2,),即第 1、2、4、8、16... 位。其余位置存放数据位。

k=4(数据 D4D3D2D1),r=3 为例:

位编号7654321
内容D4D3D2P3D1P2P1

分组规则

校验位 Pj(位于第 2j1 位)负责校验所有位编号的二进制表示中第 j 位为 1的位。

7 位海明码中,各位编号的二进制表示:

位编号二进制属于校验组
1001P1
2010P2
3011P1,P2
4100P3
5101P1,P3
6110P2,P3
7111P1,P2,P3

各校验组的覆盖范围:

校验位覆盖位编号覆盖的数据/校验位
P11, 3, 5, 7P1,D1,D2,D4
P22, 3, 6, 7P2,D1,D3,D4
P34, 5, 6, 7P3,D2,D3,D4

编码过程

对每个校验组做偶校验(该组所有位含校验位自身的异或为 0):

P1=D1D2D4P2=D1D3D4P3=D2D3D4

检错与纠错

接收端对每个校验组重新计算偶校验,得到故障字(syndrome)S3S2S1

S1=P1D1D2D4S2=P2D1D3D4S3=P3D2D3D4

故障字的值 = 出错位的编号:

故障字 S3S2S1含义
000无错误
001第 1 位(P1)出错
010第 2 位(P2)出错
011第 3 位(D1)出错
100第 4 位(P3)出错
101第 5 位(D2)出错
110第 6 位(D3)出错
111第 7 位(D4)出错

将对应位取反即完成纠错。

为什么 syndrome 恰好等于出错位编号? 因为出错位参与了哪些校验组,那些组的 syndrome 就为 1。把各组的 syndrome 拼起来,正好是该位编号的二进制表示——这就是海明码位置编排的巧妙之处。

SEC-DED:全校验位扩展

标准海明码只能纠 1 位错。如果 2 位同时出错,故障字非零但指向一个错误的位置,"纠正"反而引入第 3 个错误。

解决方案:增加 1 位全校验位 P0,对所有 n 位做整体偶校验。

P0 校验故障字判断处理
正确(0)全 0无错误无需处理
出错(1)非 01 位错按故障字纠正
正确(0)非 02 位错报告错误,不纠正
出错(1)全 0P0 自身出错纠正 P0

这就是 SEC-DED(Single Error Correction, Double Error Detection)方案。实际内存的 ECC 就是基于这个原理——72 位码字(64 位数据 + 8 位校验)实现 SEC-DED。

交互可视化

加载可视化中...

例题

例 1:对数据 D4D3D2D1=1011 编写 7 位海明码(偶校验)。

P1=D1D2D4=111=1P2=D1D3D4=101=0P3=D2D3D4=101=0
位编号7654321
内容1010101

海明码 = 1010101

例 2:接收到 1010001(原发送 1010101,位 3 出错),检错并纠正。

位编号7654321
收到1010001
S1=H1H3H5H7=1011=1S2=H2H3H6H7=0001=1S3=H4H5H6H7=0101=0

故障字 S3S2S1=0112=3,第 3 位出错。

将第 3 位取反:01,纠正后 1010101,恢复正确。

例 3:8 位数据至少需要多少位海明校验位?SEC-DED 方案呢?

2r8+r+1r=41613,满足。

标准海明码:4 位校验位,总码长 12。

SEC-DED:加 1 位全校验位 P0,共 5 位校验,总码长 13。

端到端大例:8 位数据的完整编码—传错—纠错

真题可能给 8 位数据,规模一大最容易在分组上数错位,完整走一遍。

编码:数据 D=10011010(8 位,记 D1D8 从左到右)。校验位数:2r8+r+1r=4。校验位放第 1、2、4、8 位,数据位依次填入其余位置:

位编号123456789101112
内容P1P2D1=1P3D2=0D3=0D4=1P4D5=1D6=0D7=1D8=0

按偶校验逐组计算(组内数据位异或):

  • P1(管 1,3,5,7,9,11)=10111=0
  • P2(管 2,3,6,7,10,11)=10101=1
  • P3(管 4,5,6,7,12)=0010=1
  • P4(管 8,9,10,11,12)=1010=0

码字(第 1 → 12 位):0 1 1 1 0 0 1 0 1 0 1 0

传错:接收方收到的码字第 10 位由 0 变 1。

纠错:对四个组重新做偶校验,违例记 1:

  • S1:组 {1,3,5,7,9,11} 不含第 10 位 → 校验通过,S1=0
  • S2:组 {2,3,6,7,10,11} 含第 10 位 → 违例,S2=1
  • S3:组 {4,5,6,7,12} 不含 → S3=0
  • S4:组 {8,9,10,11,12} 含 → S4=1

故障字 S4S3S2S1=10102=10,直接指向第 10 位,取反即纠正。✓

规模变大后分组别靠背——用"位编号二进制里第 j 位是否为 1"现场推:10=10102,第 2、4 位为 1,所以它恰好属于 P2P4 两组,与上面违例的两组完全吻合。

考点清单

  • [ ] 校验位数量公式:2rk+r+1
  • [ ] 校验位放在第 20,21,22,
  • [ ] 分组规则:位编号二进制中第 j 位为 1 则归入 Pj
  • [ ] 编码时对各组做偶校验求校验位
  • [ ] 故障字 = 出错位编号(全 0 表示无错)
  • [ ] 标准海明码:d=3,纠 1 位或检 2 位(二选一)
  • [ ] SEC-DED:加全校验位 P0d=4,同时检 2 纠 1

真题练习