差错控制

💡 低优先级
说实话本节细节极多但是考查频率很低,考的话一般是在选择题考一题,这一节的几个知识点说实话只能硬背了,大家可以根据自身精力决定要不要搏一搏这可能出现的两分。

分类

按照编码能够完成的功能,可以分为 检错编码纠错编码 两类。

  • 检错(Error Detection):只能判断数据在传输或存储过程中是否发生了错误,但无法确定错误的位置,因此不能恢复原始数据。
  • 纠错(Error Correction):不仅能够检测错误,还能够确定错误的位置,并自动恢复正确的数据。

常见的差错控制编码如下:

  • 检错编码:奇偶校验码、循环冗余码(CRC)
  • 纠错编码:海明码(Hamming Code)

奇偶校验码

奇偶校验码(Parity Check Code)是一种 简单高效 的错误检测机制,广泛应用于数据传输和存储系统中,用于发现传输过程中发生的错误。其核心思想是在原始数据后增加 1 位校验位(Parity Bit),使整个数据(原始数据 + 校验位)中 “1” 的总数满足预先规定的奇偶规则

奇偶校验码分为 奇校验偶校验 两种。

  • 奇校验规则:数据(包括校验位)中 “1” 的总数为奇数
  • 偶校验规则:数据(包括校验位)中 “1” 的总数为偶数
注意

为什么奇校验中,原始数据已有奇数个 “1” 时,校验位反而为 0?

需要注意的是,校验位本身并不表示奇偶性,它的作用是使 整个数据(原始数据 + 校验位) 满足规定的奇偶规则。

例如采用 奇校验

  • 若原始数据中已经有 奇数个 “1”,说明已经满足奇校验要求,因此校验位设置为 0,保持总数不变。
  • 若原始数据中有 偶数个 “1”,则需要补一个 1,使总数变为奇数,因此校验位设置为 1

偶校验的原理完全相同,只不过目标变成了使 “1” 的总数为偶数

类型数据中 “1” 个数校验位接收端判定
奇校验偶数1若收到后 “1” 的总数不是奇数,则检测到错误。
奇校验奇数0若收到后 “1” 的总数不是奇数,则检测到错误。
偶校验奇数1若收到后 “1” 的总数不是偶数,则检测到错误。
偶校验偶数0若收到后 “1” 的总数不是偶数,则检测到错误。
a1a2a3a4b1b2b3b4生成器r0a1a2a3a4b1b2b3b4q0决策电路检查器校验码s0伴随码syndrome接收拒绝EncoderEncoder发送端接收端不可靠的信道

奇偶校验码的 工作过程 如下:

  • 发送端:统计原始数据中 “1” 的个数,根据奇校验或偶校验规则计算校验位,并将校验位附加到原始数据后一起发送。
  • 接收端:对接收到的数据(包括校验位)再次统计 “1” 的个数,检查是否满足预设的奇偶规则;若不满足,则说明传输过程中发生了错误。

需要注意的是,奇偶校验码只能 检测错误,不能 纠正错误,因为它无法确定出错比特的位置。此外,它能够检测 任意奇数个比特错误(例如 1 位、3 位、5 位错误),但 无法检测偶数个比特错误(例如 2 位、4 位错误)。

检错能力是否支持
单比特错误检测
任意奇数个比特错误检测
偶数个比特错误检测
错误定位
错误纠正

循环冗余码

循环冗余校验(CRC,Cyclic Redundancy Check)是一种常用的数据完整性校验方法,广泛应用于数据传输和存储系统中,用于检测数据在传输过程中是否发生了错误。

核心思想 是将数据视为一个二进制多项式,并使用预先约定好的 生成多项式 对其进行 模 2 除法,最终所得的余数就是 CRC 校验码

模 2 除法

CRC 中最核心的运算就是 模 2 除法(Modulo-2 Division)

它与我们熟悉的十进制长除法过程基本相同,不同之处在于,模 2 除法中的 减法运算被替换为了按位异或(XOR)运算,整个计算过程中 没有借位

因此,模 2 除法可以简单理解为:

  • 将生成多项式与当前被除数的最高位对齐。
  • 若当前最高位为 1,则与生成多项式进行一次 按位异或
  • 若当前最高位为 0,则无需计算,直接向右移动一位。
  • 重复上述过程,直到所有数据处理完成,最后剩余的几位就是 CRC 校验码
1100除数 →1101)1011000← 被除数(数据 + 补 0)1101011000011010000100← 余数(CRC 校验码)最高位为 1→ 与除数异或除数(每次异或运算的操作数)余数(长度 = 除数长度 − 1)

由于整个过程中只涉及 异或移位 运算,因此 CRC 十分适合使用硬件电路实现,计算效率很高。

校验流程

Data
Divisor
000....0
CRC
Sender
Data
CRC
Data
CRC
Divisor
Remainder
Receiver
n bits
n-1 bits
zero accept
non-zero reject

CRC 校验码的生成与校验过程如下:

  1. 确定生成多项式
    发送端和接收端事先约定好同一个 生成多项式

  2. 扩展原始数据
    若生成多项式共有 k 位,则在原始数据末尾补 k−1 个 0,得到扩展数据。

  3. 计算 CRC 校验码
    使用扩展数据对生成多项式进行 模 2 除法,所得余数就是 CRC 校验码

  4. 发送数据
    将 CRC 校验码附加到原始数据末尾,组成完整的数据帧并发送。

  5. 接收校验
    接收端收到数据后,再次使用相同的生成多项式进行 模 2 除法。若余数为 0,则说明数据未检测到错误;否则说明数据在传输过程中发生了错误。

发送方

假设原始数据为:1010001101,选用的生成多项式为:110101,则对应的多项式形式为:

发送方计算 CRC 校验码的过程如下:

  1. 扩展数据:生成多项式共有 6 位,因此在原始数据末尾补上 6 - 1 = 50,得到扩展数据:

    101000110100000
    
  2. 进行模 2 除法:使用扩展数据对生成多项式进行 模 2 除法(实际计算过程中使用异或操作)。

CRC 模 2 除法计算过程数据 1010001101,生成多项式 110101,扩展数据 101000110100000生成多项式(除数)异或结果最终余数 (CRC)商 (不参与编码)商:1 1 0 1 0 1 0 1 1110101)1 0 1 0 0 0 1 1 0 1 0 0 0 0 01 1 0 1 0 11 1 1 0 1 11 1 0 1 0 11 1 1 0 1 01 1 0 1 0 11 1 1 1 1 01 1 0 1 0 11 0 1 1 0 01 1 0 1 0 11 1 0 0 1 01 1 0 1 0 10 1 1 1 0步骤说明每次取当前高位与生成多项式按位异或异或后的结果向右移一位继续除仅看首位是否为 1,决定该位商 0/1最终余数即为 CRC 校验码 01110关键规则1 ⊕ 1 = 0, 0 ⊕ 0 = 01 ⊕ 0 = 1, 0 ⊕ 1 = 1(模 2 减法 = 按位异或,无借位)最终发送帧 = 原始数据 + CRC 校验码101000110101110

最终得到余数:

01110

因此,发送的数据帧为:

1010001101 01110

接收方

继续以上述例子进行说明,接收方收到的数据为:

101000110101110

接收方同样使用生成多项式 110101 进行 模 2 除法

CRC 模 2 除法校验过程(接收方)接收数据 101000110101110,使用同一生成多项式 110101 进行模 2 除法生成多项式(除数)异或结果最终余数(应为 0)商 (不参与判断)商:1 1 0 1 0 1 0 1 1110101)1 0 1 0 0 0 1 1 0 1 0 1 1 1 01 1 0 1 0 11 1 1 0 1 11 1 0 1 0 11 1 1 0 1 01 1 0 1 0 11 1 1 1 1 01 1 0 1 0 11 0 1 1 1 11 1 0 1 0 11 1 0 1 0 11 1 0 1 0 10 0 0 0 0步骤说明用同一生成多项式按位异或异或结果右移一位继续除商不用于判断,只看最终余数余数 = 0 表示校验通过判断规则余数 = 0:数据帧未被破坏 ✓余数 ≠ 0:传输中发生错误 ✗(接收方与发送方使用相同多项式)最终余数为0,校验通过101000110101110 ÷ 110101 → 余数 =0

最终余数为:

0

说明数据在传输过程中 未检测到错误,因此 校验通过


为什么接收方不需要重新补 0?

有人说,接收方也可以采用另一种等价的校验方式:

  1. 从接收帧中分离出原始数据和 CRC 校验码;
  2. 在原始数据后重新补上 (r) 个 0
  3. 重新计算 CRC 余数;
  4. 将重新计算出的余数与接收到的 CRC 校验码进行比较。

即判断:

其中, 是接收到的数据部分, 是接收到的 CRC 字段, 是生成多项式。

这种方法在数学上与直接对完整接收帧进行模 2 除法是等价的。不过在一般的 CRC 原理讲解和硬件实现中,通常采用更直接的方式:

然后检查余数是否为全 0

海明码

海明码(Hamming Code)是一种用于 错误检测纠正 的编码方案,通常用于数据传输和存储系统中。它的主要目标是检测和纠正数据中的 单比特错误

海明码的核心思想是在 数据位 之间插入一定数量的 校验位(也称为奇偶校验位),使得每个校验位都负责检查一组特定的位。校验位的数量取决于数据位的数量,并且它们的位置通常是 2 的幂次(即第 1 位、第 2 位、第 4 位……)。

生成过程

以一个 实例 说明海明码的 生成和纠正 过程:

  • 步骤 1:确定校验位数量

假如我们的数据是 ,也就是 位。根据海明码的原则,我们需要确定足够的校验位 来满足以下条件:

对于 (数据位),我们找到最小的 3

注意

对于 位数据,应该有多少位校验位

假设我们有 位数据,我们需要添加 位校验位,那么校验位的总数必须满足以下条件:

所有数据位和校验位的总数加起来可以由校验位来表示。也就是说,每一位数据位和校验位在位模式中都有一个唯一的表示。这意味着 必须至少等于 ,其中加 是因为校验位模式全为零(即没有错误)的情况也必须被考虑在内,即

  • 步骤 2:放置校验位和数据位

首先将校验位( )插入到数据位中的适当位置。校验位下标是 2 的幂( )。

  • 位:校验位
  • 位:校验位
  • 位:校验位

然后再放置剩余的 数据位

  • 位:数据位
  • 位:数据位
  • 位:数据位
  • 位:数据位
位置7654321
海明码
数据110-1--
注意

注意到上述我们提到的关于校验位和数据位的第 位,下标是从 1 开始 而不是 0 开始的。

  • 步骤 3:计算校验位

首先给出位置下标的二进制表示:

位置7654321
二进制111110101100011010001
  • 检查位置 的位(最低位为 1) 。所以 ,所以
  • 检查位置 的位(次低位为 1)。这些位的异或值为 ,所以
  • 检查位置 的位(最高位为 1) 。这些位的异或值为 ,所以
p1p2p3d1d2d3d4
  • 步骤 4:生成海明码
位置7654321
海明码
数据1100110

所以, 海明码是 0110011 。任何一位的单一错误都可以通过分析 校验位 来检测并纠正。

检测和纠错

还是以 上文的例子 来说明海明码检测和纠错的过程。

假设在传输过程中第二位出现了错误,接收的码变为

首先,接收者现在要 重新计算校验位

  • (位置 1):检查二进制最低位为 1 的位置(1, 3, 5, 7),即
    • 接收到的 ,所以 ,无错误
  • (位置 2):检查二进制第二位为 1 的位置(2, 3, 6, 7),即
    • 接收到的 ,所以 ,有错误
  • (位置 4):检查二进制第三位为 1 的位置(4, 5, 6, 7),即
    • 接收到的 ,所以 ,无错误
1100100p1p2p3d1d2d3d411001001100100p1' = 0p2' = 1p3' = 0

可以看到有错误发生,接下来需要 生成错误模式

错误模式为二进制 010,十进制值为 2,表示错误在位置 2(即 )。

最后一步是 纠正错误:位置 2 的值 从 0 翻转为 1,得到纠正后的码字:

位置7654321
海明码
修改前1100100
修改后1100110

现在,海明码回到了正确的 0110011 状态。

海明距离

在数据传输或存储过程中,比特可能会受到噪声干扰,从 0 变成 1,或者从 1 变成 0,这种现象称为 比特翻转

例如,发送端原本发送:101101,接收端实际收到:100111

对比两个比特序列可以发现,第 3 位和第 5 位发生了变化,因此一共发生了 2 位错误

这种“两个等长比特序列在多少个位置上不同”的数量,就称为它们之间的 海明距离

1
0
0
1
0
1
1
0
1
1
0
1
1
0
1
0
A
B
0
1
0
0
1
1
0
0
XOR Bit Operations

设两个长度相同的比特序列分别为:

则它们之间的海明距离记作:

其值等于满足 的位置个数。

因此,如果发送码字为 ,接收序列为 ,并且:

就说明传输过程中一共发生了 位错误。

编码集

应用层产生的原始数据可以由 01 任意组合。对于长度为 的原始信息,一共有 种可能的比特串。

为了使数据具备检错或纠错能力,发送端会对原始信息进行差错控制编码,将每个长度为 原始信息 转换为长度为 码字,通常有:

其中,多出的 位用于承载校验信息,因此称为 冗余位

编码过程可以表示为:

其中, 表示编码规则能够产生的所有码字的集合,称为 编码集,也称为 码(code)

原始信息k = 2 位,共 2ᵏ = 4 种00原始信息 001原始信息 110原始信息 211原始信息 3编码映射{0,1}ᵏ → C ⊆ {0,1}ⁿ冗余位 = n − k 位n 位比特空间(n = 3)全部 2ⁿ = 8 种比特串编码集 C(合法码字)共 2ᵏ = 4 个000← 00 的编码011← 01 的编码101← 10 的编码110← 11 的编码非法比特串共 2ⁿ − 2ᵏ = 4 个001不在 C 中010不在 C 中100不在 C 中111不在 C 中检错原理接收端若收到不属于 C 的比特串,即可判定传输发生了错误

全部可能的 位比特串共有 个,但编码规则通常只使用其中的 个作为码字。其余 比特串仍然是正常的二进制序列,只是不属于当前编码集。

例如,假设用 2 位信息表示四种原始数据,并将其编码为 3 位码字:

那么该编码集为:

在全部 个 3 位比特串中,只有这 4 个属于编码集。

接收端事先知道发送端只会发送编码集中的码字。因此,当接收到一个不属于编码集的比特串时,就可以判断数据在传输或存储过程中发生了错误。

最小海明距离

编码集 最小海明距离 定义为任意两个 不同码字之间海明距离的最小值

通常也将其简记为

最小海明距离反映了编码集中距离最近的两个合法码字相隔多远。它直接决定编码集的容错能力:

  • 最多可以 检测 的错误位数为:
  • 最多可以 纠正 的错误位数为:
检测和纠错位数是如何得到的

其原因可以从码字之间的距离进行理解。

假设两个合法码字 的距离为 。要把 经过比特翻转变成另一个合法码字 ,至少需要翻转 位。因此,只要错误位数小于 ,错误后的序列就不可能成为另一个合法码字,接收端便能够判断数据发生了错误。

所以最多可以检测 位错误。

对于纠错,接收端通常采用 最近邻译码:将接收到的序列判定为与其海明距离最近的合法码字。

要保证接收序列仍然唯一地靠近原码字,原码字周围可纠正的范围不能与其他码字的可纠正范围重叠。因此需要满足:

由此得到:

最小海明距离越大,码字在整个比特空间中越“分散”,发生一定数量的比特翻转后,接收端越容易区分原始码字。


例如,设编码集为:0000, 0110, 1011

三组码字之间的海明距离分别为:

  • 00000110 的海明距离为 2,第 2、3 位不同;
  • 00001011 的海明距离为 3
  • 01101011 的海明距离为 3

因此,该编码集的最小海明距离为:

根据公式,该编码集最多可以:

  • 检测 位错误;
  • 纠正 位错误。

也就是说,它能够发现单比特错误,但无法保证确定原始码字。

例如,接收到 0010,它与 00000110 的海明距离都为 (1)。因此,接收端虽然知道发生了错误,但无法判断原本发送的是哪个码字。

如果想要稳定地纠正 1 位错误,就必须使任意两个合法码字之间至少相隔 3 位,即:

海明码示例

海明码(Hamming Code) 是一种经典的线性分组码,其最小海明距离为 。这意味着:

  • 可以 检测最多 2 位错误
  • 可以 纠正 1 位错误

接收端在解码过程中,会计算出一个称为 伴随式(syndrome) 的比特序列,用于判断是否发生了错误,以及错误的位置:

  • 若伴随式为全零,说明数据未被破坏;
  • 若伴随式为非零,且对应某个位的错误模式,则可准确定位并纠正该位;
  • 若发生 2 位错误,伴随式可能不唯一,可检测但不可纠正,因为错误位置无法唯一确定。