想象你是一座奢侈品仓库的负责人。仓库里有几十个货架,每一件瓷器都价值连城。你面临两种头疼的问题:一是搬运中可能有某件瓷器被磕出细纹(单个比特翻转),你得在第一时间找出是哪一件;二是寄出的包裹经过十几个中转站,你怕有人偷偷开箱调包(突发错误),但你拿不出确凿证据。 为了对付第一种风险,你雇了几位“巡检员”——他们按照一套精巧的网格分工巡逻。某天一个货架出了状况,几位巡检员碰头一核对:“我负责的A区有问题”“我负责的B区也有问题”“我的C区一切正常”。把线索拼在一起,你立刻锁定了那个出事的货架——这就是海明码的纠错原理:用少量冗余的“巡检员”精确定位并修复单点故障。 为了对付第二种风险,你在每个包裹上贴一张“防伪封条”——封条上的数字由货物内容经过一道特殊算法算出,收货方重新算一遍,对不上就说明包裹被动过手脚。这就是CRC循环冗余校验:用数学指纹检测数据是否被篡改。一个能“定位修复”,一个能“发现异常”,两大编码构成了数字世界传输与存储安全的两道防线。

岗位关联

掌握海明码与CRC,你就能看懂内存ECC为何能悄悄修复数据,也能理解网卡在微秒级完成帧校验的底层逻辑——这是从“会用网络”到“懂网络”的分水岭,也是排查硬件级数据异常的必备内功。

目录
  1. 可视化演示
  2. 海明码的校验位设计
  3. 海明码的纠错流程
  4. CRC的生成多项式与除法
  5. CRC的硬件实现
  6. 典型应用场景
  7. 海明码与CRC的对比
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示海明码校验位编码原理、单比特错误定位纠错流程与CRC多项式除法校验过程,三步演示从编码到纠错到校验的完整链路,可切换模式查看不同阶段。

本节配有交互动效(进入视口后自动加载,约 3KB)。

海明编码 校验位位于2的幂次位置 2^r≥m+r+1 P1P2P4覆盖特定数据位

海明码的校验位设计

想象你管理着一座堆放古董瓷器的仓库。货架编号从1排到N,每件瓷器都价值连城,最怕搬运时磕碰——一个瓷瓶碎了,你得知道具体是哪个位置的碎了才能补货。你雇了几位巡检员,但工钱不菲,人数必须精打细算。一位巡检员只能报告“这排有没有碎”;两位巡检员各按一套分区巡逻,组合起来能区分4种情况;三位就是8种。问题来了:要在 N 个货架中定位任何一处损坏,最少要雇几人?

计算机里的比特,就是那些货架上的瓷器。海明码用 r 个校验位(巡检员)看护 n 个数位(货架),校验位的数量必须满足一个不等式:所有校验位能组合出的状态数,至少要能区分“一切正常”以及 n+r 个位置中任何一处出错——合计一共需要标识 n+r+1 种情况。

2r≥n+r+1\displaystyle 2^r \geq n + r + 1

1. 数据位数 n:原始有效信息占用的比特数。例如要传输4位数据,n=4。

nn

2. 校验位数 r:额外添加的冗余比特数,它们不携带新信息,只负责“盯梢”。

rr

3. 状态总数 2^r:r 个校验位能组合出 2^r 种“口供组合”,如同 r 个巡检员各报“正常/异常”,能形成 2^r 种汇报模式。

2r2^r

4. 待区分情况 n+r+1:码字总长 n+r 个位置,加上“无错误”这一种情况,就是需要区分的全部情形。

n+r+1n + r + 1

第二件要事:校验位放在哪里?答案是 2 的幂次位置:第 1、2、4、8……位。这么做有一个精妙的好处——每个校验位只属于一个校验组,数值互不影响,接收端可以独立地算出每一位,不会出现“牵一发而动全身”的混乱。

pi=2 i−1,i=1,2,…,r\displaystyle p_i = 2^{\,i-1}, \quad i = 1, 2, \dots, r

1. 第 i 个校验位 p_i:从 1 开始计数,第1个校验位、第2个校验位、第3个校验位……依次排列。

pip_i

2. 位置公式 2^(i-1):第 i 个校验位放在码字的第 2^(i-1) 位,即位置 1、2、4、8、16……这些位置上。

2 i−12^{\,i-1}

3. 二进制独特性:这些位置编号的二进制表示只有单独一个 1(如 1=001、2=010、4=100),所以每个校验位只出现在自己的校验组里,不会干扰其他校验位的计算。

pi=2 i−1p_i = 2^{\,i-1}

于是,雇几个巡检员、他们站在哪些位置,都有了数学依据:正如不等式决定了人工预算,位置公式则确保每个人的“领地”清爽独立。海明码的骨架就此搭好——接下来就是让巡检员们开始干活了。

海明码的纠错流程

巡检员们上岗了。他们手里各有一张巡逻清单,清单不是随便划的,而是按照货架编号的二进制编码来分:位置编号的二进制表示中,第 i 位为 1 的位,就归第 i 个巡检员管。于是位置3(二进制 011)同时出现在1号和2号巡检员的清单上;位置5(二进制 101)则出现在1号和3号的清单上。这样,当某个位置出错时,哪些巡检员会拉响警报,就构成了一串独一无二的二进制编码。

接收端做同样的分组——把每个组内的所有位做异或运算。若某组异或结果为1,说明这一组内有奇数个位出错了。注意,这个“分组”把校验位自己也算进去了:校验位的值在发送时就被设计成让每组异或结果为0,所以接收端的异或结果天然就是“是否出错”的指示器。

S=P1⋅1+P2⋅2+P3⋅4\displaystyle S = P_1 \cdot 1 + P_2 \cdot 2 + P_3 \cdot 4

1. 各组校验结果 P_i:每组做异或的结果,正常为0,异常为1。它是一份“证词”。

Pi=⨁j∈组ibjP_i = \bigoplus_{j \in \text{组}i} b_j

2. 加权求和:第 i 组的结果乘以 2^(i-1),再把三项加起来。因为位置编号的二进制中各位的权重正是 1、2、4。

S=P1+2P2+4P3S = P_1 + 2P_2 + 4P_3

3. 校正子 S:S=0 表示无错;S 非零时,它的数值直接告诉我们出错位置。比如 S=6,说明第6位翻转了。

S=出错位编号S = \text{出错位编号}

看,这就是交叉汇报的力量——每个人只报告自己辖区内的异常,但把所有人的证词拼在一起,谜底就浮出水面了。海明码不需要“挨个检查”,只需要 3 个异或门和一次小加法,就能在纳秒内锁定肇事比特,然后把它取反,数据恢复如初。

CRC的生成多项式与除法

处理完仓库的磕碰,你还要对付另一个隐患:快递。瓷器打包寄往外地,要经过十几个中转站,你怀疑有人偷偷开箱。你想了一个点子:不用昂贵的巡检员,而是在每件包裹上贴一枚“防伪封条”——封条上的数字由货物内容用一套神秘算法算出来,收货方重新一算,对不上就说明箱子被动过。这枚封条,就是 CRC 校验码。

CRC 的数学舞台是二进制多项式。把信息比特 1011 写成多项式 x³+x+1,把商定的“神秘算法”叫做生成多项式 G(x)。发件方把信息左移 r 位(预留出校验码的位置),用 G(x) 做模2除法,把余数 R(x) 贴在信息尾部。这里的“模2除法”很特别:每一步减法都用异或代替,既不借位也不产生进位。

R(x)=(M(x)⋅xr) mod G(x)\displaystyle R(x) = \left( M(x) \cdot x^r \right) \bmod G(x)

1. 信息多项式 M(x):原始数据的每一位对应 x 的幂的系数。比如 1011 = x³ + x + 1。

M(x)=mk−1xk−1+⋯+m1x+m0M(x) = m_{k-1}x^{k-1} + \cdots + m_1 x + m_0

2. 左移 r 位:乘以 x^r 相当于在信息末尾补 r 个0,腾出 r 位的空间来放校验码。

M(x)⋅xrM(x) \cdot x^r

3. 模2除法取余:用 G(x) 做模2除法,余数的最高次数必然小于 r,因此余数只占 r 位。

 mod G(x)\bmod G(x)

4. 余数即校验码 R(x):把 r 位的余数拼接到左移后的信息后面,组成完整的发送码字。

T(x)=M(x)⋅xr+R(x)T(x) = M(x) \cdot x^r + R(x)

收件方对完整码字再做一次同样的除法,如果余数为0,说明封条完好;余数非0则说明数据被篡改过。

T(x) mod G(x)=0\displaystyle T(x) \bmod G(x) = 0

1. 接收码字 T(x):收件方拿到的完整比特串,包含原始信息和 CRC 校验码。

T(x)T(x)

2. 再做一次除法:用同一个 G(x) 去除 T(x),因为 T(x) 是左移后的信息加上余数,理论上应当整除。

T(x)÷G(x)T(x) \div G(x)

3. 余数判据:整除(余数为0)说明数据完好;产生余数说明传输中发生了错误。

T(x) mod G(x)=0  ⟺  无误T(x) \bmod G(x) = 0 \iff \text{无误}

与海明码的“精准定位”不同,CRC 的封条只回答一个问题:这箱子被动过没有?它不告诉你动了哪一件,但足以让收货方决定“拒收重发”——在可靠传输协议中,重发远比现场修复更划算。

CRC的硬件实现

制作防伪封条的工艺,比你想象中简单——只需要一枚模板(生成多项式)和一颗图章(异或门)。不需要乘法器、不需要除法器,几块小电路就能在数据流过的一瞬间完成盖章。这一切的核心,是一种叫做“线性反馈移位寄存器”(LFSR)的电路。

模2除法的每一次“减法”都退化为异或:1 与 1 相遇立即抵消为 0,没有借位、没有进位。这意味着电路里只需要一种逻辑门——异或门。而 LFSR 的结构更是直接由生成多项式的形状决定:寄存器的每一位串联起来,在系数为 1 的位置引出反馈线,接入异或门,再把结果送回寄存器首位。

G(x)=xr+gr−1xr−1+⋯+g1x+1\displaystyle G(x) = x^r + g_{r-1}x^{r-1} + \cdots + g_1 x + 1

1. 最高次项 x^r:生成多项式的次数 r 决定了寄存器的位数(也是校验码的位数)。

xrx^r

2. 中间系数 g_i:值为 1 的系数位对应一条反馈抽头,值为 0 则直接跳过。

gr−1,…,g1g_{r-1}, \dots, g_1

3. 常数项 1:最低位恒为 1,保证余数不会出现“除尽”时的退化情况。

+1+1

这台“盖戳机”的速度快得惊人。以千兆以太网为例,数据以每秒 1G 比特流过,CRC-32 电路在线计算,延迟以纳秒计。你还在核对快递单,封条已经悄悄盖好并校验完毕了——这正是硬件实现的魅力:用最少的资源,在数据流动的途中完成数学计算。

典型应用场景

现在你回到仓库总经理的位置。不同的货物,你会选择不同的安保方案:传世字画派武装押运(海明码),普通标件贴防伪封条(CRC)。数字世界里,这个决策同样讲究“量体裁衣”——没有最好的编码,只有最合适的编码。

内存 ECC:服务器内存是数据暂存的黄金库,宇宙射线和热噪声会导致比特随机翻转。ECC 内存采用海明码的升级版(SEC-DED),每 64 位数据附加约 8 位校验。单比特错误在读取时自动纠正,用户毫无感知;双比特错误则触发告警,防止数据继续被污染。这是海明码“纠错”能力的经典战场。

网络传输:以太网帧在嘈杂的铜缆和光纤中穿行,噪声容易引发成串的突发错误。网卡在发送帧时计算 CRC-32,把 4 字节的帧校验序列(FCS)附在帧尾;接收时重新计算,不匹配就丢弃该帧。因为网络协议允许重传,所以“检测到就重发”远比“试图修复”更高效——这是 CRC“检错”优势的典型体现。

存储校验:磁盘和 SSD 也可能发生“静默数据损坏”——硬件报错但数据已错,普通校验发现不了。ZFS、Btrfs 等现代文件系统在每个数据块旁存储校验和,读取时即时验证,发现损坏就从冗余副本恢复。RAID 控制器同样大量使用 CRC 来做一致性校验。

金子用保险箱,瓷器用海绵,标签用封条,各有各的妙处。选海明码还是 CRC 的黄金法则:需要现场修复且错误以单比特为主,选海明码;错误可能是一串突发且允许重传,选 CRC。

海明码与CRC的对比

巡检员与封条,此刻站在你面前等你做最终抉择。它们都能发现数据异常,但能力边界截然不同:巡检员能告诉你“哪件瓷器碎了”并当场补上,封条只能告诉你“包裹被动过”,要挽回损失还得靠重寄。

从信息论的角度看,海明码把冗余花在了“位置编号”上——校正子的大小直接映射到出错位置,因此它天然适合纠正单比特错误。而 CRC 把冗余花在了“特征提取”上——用多项式除法把数据揉成一个高强度的指纹,只要有任何一处异动,指纹就会对不上。两者的根本差异可以浓缩为一句话:海明码是“哪里坏了修哪里”,CRC 是“坏了就重新来”。

冗余率=rn+r\displaystyle \text{冗余率} = \frac{r}{n + r}

1. 冗余位 r:校验位(或 CRC 校验码)的位数,是为安全付出的额外带宽。

rr

2. 总码长 n+r:信息位加上校验位的完整长度,是实际占用信道的比特数。

n+rn + r

3. 冗余率:冗余位占总码长的比例。海明码随数据增长(如 8 位数据要 4 位校验,冗余率约 33%),CRC 则固定开销(如 CRC-32 对任意长数据都只加 32 位)。

rn+r\frac{r}{n+r}

回到整体:两道防线,各司其职。海明码靠着分层巡检的巧思,用最少的人手在单比特错误面前做到“现场修复”;CRC 靠着数学指纹的韧性,在无处不在的突发噪声面前做到“明察秋毫”。理解了它们,你就理解了计算机系统如何在资源与安全之间做出优雅的权衡。

AI 应用场景

云服务器内存 ECC 故障自愈

阶段:数据存储与可靠性保障

解决的问题:数据中心服务器内存每天被宇宙射线击中多次,产生随机单比特翻转。传统无校验内存会让这些悄悄的错误写入计算结果,造成难以追踪的“软错误”。ECC 内存基于海明码变体(SEC-DED)工作,在每次内存读取时自动纠正单比特错误并报告双比特错误,让系统在用户无感知的情况下完成“自我愈合”。

具体案例:某云厂商在 CPU 和内存之间部署 ECC 校验后,内部统计显示单比特错误纠正事件的频率约为每千条内存每月数十次。这些纠正全部由内存控制器硬件完成,操作系统对此一无所知。当某个内存条的错误频率异常升高,带外监控系统会将其标记为“亚健康”并触发热迁移流程,提前替换硬件。

高速网络帧的 CRC-32 在线校验

阶段:数据传输完整性验证

解决的问题:以太网在物理层传输时容易受电磁干扰产生突发错误,如果让数据帧“带伤”进入上层协议,会造成数据静默损坏。网卡硬件在发送方向对每个帧计算 CRC-32 并附加 FCS,在接收方向重新计算,一旦发现余数不为 0,立即丢弃该帧并触发重传机制。

具体案例:在 25Gbps 数据中心网络中,一份 64 字节的最小以太网帧只需不到 3 纳秒就能被网卡完成 CRC 校验。正是这种硬件级的速度,让“边收边验”成为可能,而 CRC-32 多项式对最大长度 1500 字节 MTU 的帧有着几乎完美的突发错误检测能力,漏检率约为 1/2³²。

文件系统的静默数据损坏防护

阶段:数据持久化与完整性审计

解决的问题:磁盘坏道、SSD 读干扰等问题可能让数据在被读取时早已损坏却没有任何报错,这种“静默损坏”是存储系统最隐蔽的敌人。现代文件系统如 ZFS 采用端到端校验:每次写入数据块时生成校验和,每次读取时重新计算并比对,在损坏发生的第一时刻发现并自动从冗余副本恢复。

具体案例:某存储集群启用 ZFS scrubbing(定期完整性巡检)后,在一次全量扫描中发现了 7 个静默损坏的数据块,全部通过校验和检测定位并由 RAID-Z 的冗余数据自动修复,而传统 EXT4 文件系统对此类损坏毫无察觉。

Python 演示

python70 行
# -*- coding: utf-8 -*-"""海明码(7,4)与CRC-3完整演示"""  def hamming_encode(d):    """海明码(7,4)编码:输入4位数据,输出7位码字"""    b = [0] * 7    # 数据位映射到位置3,5,6,7    b[2], b[4], b[5], b[6] = d[0], d[1], d[2], d[3]    # 校验位放在位置1,2,4    b[0] = b[2] ^ b[4] ^ b[6]    b[1] = b[2] ^ b[5] ^ b[6]    b[3] = b[4] ^ b[5] ^ b[6]    return b  def hamming_syndrome(b):    """海明码校正子:返回0表示无错,否则返回出错位置"""    s = b[0] ^ b[2] ^ b[4] ^ b[6]    s |= (b[1] ^ b[2] ^ b[5] ^ b[6]) << 1    s |= (b[3] ^ b[4] ^ b[5] ^ b[6]) << 2    return s  def hamming_correct(b):    """海明码纠错:单比特翻转自动纠正"""    s = hamming_syndrome(b)    if s:        b[s - 1] ^= 1    return b, s  def crc_encode(data, poly):    """CRC编码:返回完整码字与校验码"""    r = len(poly) - 1    work = data[:] + [0] * r       # 信息左移r位    for i in range(len(data)):        if work[i]:            for j in range(1, len(poly)):                work[i + j] ^= poly[j]   # 模2除法    remain = work[len(data):]    return data + remain, remain  def crc_check(code, poly):    """CRC校验:余数全为0表示无误"""    r = len(poly) - 1    work = code[:]    for i in range(len(code) - r):        if work[i]:            for j in range(1, len(poly)):                work[i + j] ^= poly[j]    return not any(work[len(code) - r:])  if __name__ == "__main__":    # 海明码演示    data = [1, 0, 1, 1]    code = hamming_encode(data)    print("海明码(7,4)编码:", data, "->", code)    code[5] ^= 1    fixed, s = hamming_correct(code)    print("翻转第6位后 校正子 =", s, " 纠正后:", fixed)     # CRC演示    g = [1, 1, 0, 1]   # G(x)=x^3+x^2+1    tx, crc = crc_encode([1, 1, 0, 1, 0], g)    print("CRC编码: 信息11010 校验码", crc, "-> 完整码字", tx)    tx[4] ^= 1    print("接收端校验 余数为0?", crc_check(tx, g))
目的:用纯 Python 链表复现海明码(7,4)的编码-翻转-纠错全过程,以及 CRC 的多项式除法编码-校验流程,帮助理解两种编码的核心算法。
  1. b[2], b[4], b[5], b[6] = d[0], d[1], d[2], d[3]把4位原始数据安插到海明码的位置3、5、6、7上,位置1、2、4留给校验位。
  2. b[0] = b[2] ^ b[4] ^ b[6]计算第1组校验位:它需要让位置1、3、5、7的异或结果为0,这正是奇偶校验的本质。
  3. s |= (b[1] ^ b[2] ^ b[5] ^ b[6]) << 1把第2组异常结果左移1位(乘以2),与第1组结果按位相加,为组成校正子做准备。
  4. b[s - 1] ^= 1校正子 s 就是出错位置,直接对该位置取反,一步完成纠错——简洁得令人惊叹。
  5. work = data[:] + [0] * rCRC 编码第一步:信息左移 r 位,在后面补 r 个0,给校验码腾出空间。
  6. work[i + j] ^= poly[j]模2除法的核心:当前位为1时,从第 i 位开始与多项式系数逐位异或,实现无借位除法。
  7. return data + remain, remain把余数(校验码)拼接到信息尾部,形成最终发送的码字。
  8. return not any(work[len(code) - r:])接收端检查最后 r 位是否全为0,全0则说明除法整除,数据没有破损。

常见误区

误区我以为海明码和普通的奇偶校验一样,只能告诉我数据有没有出错,不能告诉我是哪一位出了问题。既然不能定位,那纠正就更不可能了。

正解恰恰相反,海明码的核心卖点就是“定位+纠正”。它用多个奇偶校验位组成独特的“位置编码”,校正子的数值直接等于出错位置。比如校正子 S=6,就表示第6位翻转,直接把它取反即可恢复。不要把它和单比特奇偶校验混为一谈——后者只有1个冗余位,只能表达“对/错”两种状态;而海明码有 r 个冗余位,能表达 2^r 种状态,远不止二元信息。

为何常见:因为很多教材先讲奇偶校验(只检错),跳跃到海明码时没有强调“多位校验位组合起来可以编码位置信息”这一关键跃迁,读者便很容易把两者归为一类。

误区既然海明码靠校验位工作,那我多加几个校验位岂不是纠错能力更强?干脆给8位数据加8个校验位,这样双保险总没问题了吧?

正解校验位数量由不等式 2^r ≥ n+r+1 决定。加多了只能覆盖更长的数据,并不能提升单比特纠错能力——标准海明码的码距为3,只能保证1位纠错、2位检错。若想提升纠错能力,需要重新设计码距更大的扩展海明码(如 SEC-DED),而不是简单堆砌校验位。多余校验位只会白白浪费带宽,就像给仓库雇了十个巡检员,但巡逻路线完全重复,并不能多看出什么端倪。

为何常见:“冗余越多越稳”的直觉在纠错编码领域并不成立,纠错能力取决于码字间的最小距离,而这个几何概念对初学者不够直观。

误区CRC 计算这么严谨,一定能发现传输过程中的任何错误吧?毕竟多项式除法把整个数据都揉进去了,怎么可能漏掉?

正解CRC 不能保证 100% 检出。它的本质是模2除法取余:只有当错误多项式 E(x) 恰好被生成多项式 G(x) 整除时,余数才会为 0,此时错误被漏检。好的生成多项式(如 CRC-32)利用本原多项式将漏检率压到约 1/2^r,尤其在检测突发错误方面表现极其出色,但这属于“极大概率”而非“绝对保证”。这就像防伪封条几乎不可能被仿制,但理论上总存在一种巧妙的伪造方法。

为何常见:教材常强调 CRC 检错能力极强,但没有展开漏检率的极限推导,学习者容易把“近乎完美”误解为“绝对可靠”。

误区既然 CRC 能发现数据有错,那我反向操作一下,不就能把出错的那一位找出来并修好吗?反正都是针对错误做文章。

正解CRC 是检错码,只返回“非零余数”这个事实,不包含任何错误位置信息。拿 CRC-32 来说,它有 2³² 种状态,却要区分可能的上亿种错误位置,信息量根本不够。海明码能做到精确定位,是因为它把校验位的状态数设计成恰好与位置数一一对应,代价是冗余随数据长度增长。而 CRC 固定只附加 32 位,适用于任意长度的数据,靠“检测到就重传”来兜底,这比在接收端做现场修复便宜得多。

为何常见:把“检错”和“纠错”混为一谈,没有意识到两者在信息论上有本质的冗余开销差异——定位一个错误需要的信息量远大于仅仅发现错误存在。

面试题

Q1. 海明码的校验位通常安排在码字的哪些位置?

单选题 · easy

  • A.数据位的前方位置
  • B.数据位的后方位置
  • C.2的幂次方的位置← 正确答案
  • D.任意间隔的位置

答案:C。海明码把校验位放在位置 1、2、4、8……这些 2 的幂次位上。原因是一个校验位如果放在其他位置,它的编号二进制包含多个 1,就会同时属于多个校验组,造成计算互相干扰。放在 2 的幂次位置,编号二进制只有单个 1,每个校验位只属于一个组,独立性强。这就像把巡检员安排在互不重叠的独立路线上。

Q2. CRC循环冗余校验的核心数学基础是?

单选题 · easy

  • A.多项式的模2除法← 正确答案
  • B.整数模运算求余
  • C.集合的并交补运算
  • D.概率统计抽样分析

答案:A。CRC 的全部计算建立在二进制多项式的模2除法之上:信息多项式左移 r 位后除以生成多项式,余数就是校验码。模2除法的关键在于每一位的减法都退化为异或,不借位、不进位,因此硬件上只需要异或门就能实现。其他选项如整数求余、集合运算或概率统计,都没有描述 CRC 的真实数学本质。

Q3. 内存条上使用的ECC纠错技术,通常采用哪种编码?

单选题 · easy

  • A.CRC循环冗余校验
  • B.海明码校验纠错← 正确答案
  • C.简单奇偶校验位
  • D.字符串匹配算法

答案:B。ECC 内存采用海明码的变体(通常为 SEC-DED),因为内存错误的典型形态是单比特随机翻转,而海明码恰好可以定位并纠正单个比特的错误。CRC 更适合检测突发错误,常用于网络传输;简单奇偶校验只能检错不能纠错;字符串匹配算法则与纠错编码毫无关系。

Q4. 要传输8位数据,海明码至少需要多少个校验位?

单选题 · mid

  • A.添加3个校验位
  • B.添加4个校验位← 正确答案
  • C.添加5个校验位
  • D.添加6个校验位

答案:B。代入不等式 2^r ≥ n+r+1,其中 n=8。试 r=3:2³=8,而 8+3+1=12,8≥12 不成立;试 r=4:2⁴=16 ≥ 8+4+1=13,成立。所以至少需要 4 个校验位。这个不等式保证校验位的状态数足够区分“无错误”以及所有位置的出错情况。

Q5. 关于标准海明码(7,4)的纠错机制,下列说法正确的是?

多选题 · hard

  • A.校验位占用位置1、2、4← 正确答案
  • B.能纠正任何单比特翻转← 正确答案
  • C.校正子数值直接给出错位← 正确答案
  • D.能准确定位所有双比特错误

答案:ABC。(7,4)海明码有4个数据位和3个校验位,校验位放在位置1、2、4;任意单比特翻转都会产生一个非零校正子,且校正子的值恰好等于出错位置,因此可以精确纠正。双比特错误能被检测出(校正子非零),但会被误判为某个单比特错误而无法准确定位,所以选项D错误。

Q6. 接收端计算海明码校正子 S=5,这意味着出错位在?

单选题 · mid

  • A.整个数据的第5位← 正确答案
  • B.整个数据的第3位
  • C.整个数据的第7位
  • D.整个数据的第6位

答案:A。海明码最精妙的设计就是校正子 S 与出错位置之间的直接对应。S=5 表示出错位是第5位。从分组看,位置5(二进制101)同时属于第1组(权重1)和第3组(权重4),所以这两组校验结果异常,1+4=5。这也解释了为什么“校正子翻译”如此简单——它就是出错位置的编号本身。

Q7. (7,4)海明码中第6位发生翻转后,校正子S的值等于?

单选题 · hard

  • A.6← 正确答案
  • B.7
  • C.5
  • D.3

答案:A。位置6的二进制是110,它属于第2组(权重2)和第3组(权重4),不属于第1组(权重1)。因此第2、3组校验结果异常,第1组正常,校正子 S = 0×1 + 1×2 + 1×4 = 6。S 恰好等于 6,证实了“校正子=出错位置”的设计等式。

Q8. 关于CRC校验码的特点,以下说法正确的是?

多选题 · mid

  • A.非常适合检测突发性错误← 正确答案
  • B.所用多项式次数越高检错越强← 正确答案
  • C.必须用软件逐位计算不可加速
  • D.存在极低概率的漏检情况← 正确答案

答案:ABD。CRC 对突发错误的检测能力极强,因为连续多位的错误模式很难被生成多项式整除;生成多项式的次数越高,校验位越多,漏检率按 1/2^r 指数下降。但 CRC 完全可以用线性反馈移位寄存器(LFSR)在硬件中以纳秒级速度在线计算,并非只能用软件慢速实现。只要错误多项式恰好能被 G(x) 整除,就会漏检,只是概率极低。

Q9. CRC生成多项式 G(x)=x³+x+1 对应的二进制表示是?

单选题 · hard

  • A.二进制数 1011← 正确答案
  • B.二进制数 1101
  • C.二进制数 1110
  • D.二进制数 0111

答案:A。多项式的系数决定二进制位:x³ 对应最高位 1,x² 的系数为 0(因为没有 x² 项),x¹ 对应 1,常数项 1 对应最低位 1,所以从左到右是 1011。二进制数 1101 对应 x³+x²+1,1110 对应 x³+x²+x,0111 对应 x²+x+1——这些都是不同的多项式。

Q10. 关于海明码与CRC在实际应用中的合理选择,正确的是?

多选题 · mid

  • A.内存ECC选海明码← 正确答案
  • B.网络帧校验选CRC← 正确答案
  • C.海明码能纠正错误而CRC不能← 正确答案
  • D.CRC能定位错误位而海明码不能

答案:ABC。内存错误的典型形态是单比特翻转且不允许重读,因此选海明码做现场纠正;网络传输错误多为突发且允许重传,选 CRC 做快速检测。海明码的核心能力是定位并纠正单比特错误,CRC 只能判断“有无错误”而无法定位。实际协议甚至会把两者结合使用,比如网络协议栈内层用 CRC 检错、外层靠重传恢复。