计算机原理之校验码

1.码距

  • 码距(汉明距离):两个等长编码之间不同位的个数。

    • 例如:000 和 001 的码距是1。

    • 码距决定了编码的检错和纠错能力。

    • 原始无校验的数据码,最小码距为 1

"两个等长编码之间不同位的个数",指的就是逐位比较两个长度相同的二进制串,统计对应位置上的数字(0或1)不相同的总位数。


奇偶校验的目标 :将任意两个有效编码之间的最小码距 从1增加到2。 这意味着,任何一个有效的奇偶校验码发生单比特错误(1位翻转)后,都会变成一个无效的、不满足奇偶性规则的编码,从而可以被检测出来。

2.奇偶校验

假设我们有一个4位原始数据:1101(其中已有3个"1")。

2.1. 偶校验

  • 规则 :使编码中"1"的总个数为偶数
  • 计算 :原始数据 1101 中"1"的个数 = 3(奇数)。为了变成偶数,校验位应为 1
  • 最终编码(数据位 + 校验位)1101 1
  • 验证 :整个5位编码 11011 中,"1"的个数为4(偶数),符合规则。

2.2. 奇校验

  • 规则 :使编码中"1"的总个数为奇数
  • 计算 :原始数据 1101 中"1"的个数 = 3(奇数)。为了保持奇数,校验位应为 0
  • 最终编码(数据位 + 校验位)1101 0
  • 验证 :整个5位编码 11010 中,"1"的个数为3(奇数),符合规则。

好的,我们来用一个完整的例子说明奇偶校验码的工作原理。

偶校验的例子

使用偶校验(使整个编码中"1"的个数为偶数):

原始数据:1 0 1 1(3个"1",是奇数)

  • 为了保持偶数,校验位应为 1
  • 发送:1 0 1 1 1("1"的总数=4,偶数 ✅)

接收方按奇校验检查:

  • 若收到 1 0 1 1 1(4个"1")→ 偶数 ✅,无错。
  • 若收到 1 1 1 1 1(5个"1")→ 奇数 ❌,检测到错误。
  • 若收到 0 0 0 1 1(2个"1")→ 偶数 ✅,错误地判定为无错!。

奇校验的例子

如果采用奇校验(使"1"的总数为奇数):

原始数据:1 0 1 1(3个"1",已是奇数)

  • 为了保持奇数,校验位应为 0
  • 发送:1 0 1 1 0("1"的总数=3,奇数 ✅)

接收方按奇校验检查:

  • 若收到 1 0 1 1 0(3个"1")→ 奇数 ✅,无错。
  • 若收到 1 0 0 1 0(2个"1")→ 偶数 ❌,检测到错误。
  • 若收到 0 0 0 1 0(1个"1")→ 奇数 ✅,错误地判定为无错!。

2.3 奇偶校验码特点总结表

特性 说明
增加冗余 只增加1位校验位,开销小(n位数据→n+1位传输)
检错能力 能100%检测出任意奇数个比特的错误
无法检测 所有偶数个比特的错误
纠错能力 无。只能知道"有错",但不知道哪一位错
最小码距 2(任意两个有效码字至少差2位,原始无校验的数据码最少是1位)
应用场景 内存(RAM)校验、串行通信(如UART)、简单数据传输

每个比特错误(0变1或1变0)就像按一下开关

  • 按奇数下(1, 3, 5...次) → 开关状态一定会改变(从"偶"到"奇")

  • 按偶数下(2, 4, 6...次) → 开关状态一定会回到原位(还是"偶")

3.模2除法

✅ 模2除法基本步骤(结合实例说明)

适用场景 :CRC校验、二进制多项式除法等
核心规则 :所有运算在 GF(2) 上进行 → 加减 = 异或(XOR),无进位/借位


📌 步骤总览

  1. 准备数据

    • 被除数(如 11011001
    • 除数(如 101,必须以 1 开头)
  2. 初始化窗口

    • 取被除数前 ( n ) 位(( n = \text{除数长度} ))作为当前工作区
  3. 逐位处理(共 ( \text{len(被除数)} - n + 1 ) 步)

    • 若当前窗口最高位是 1
      • 与除数做 XOR
      • 商当前位 = 1
    • 若当前窗口最高位是 0
      • 不做 XOR(等价于 XOR 全0,但通常省略)
      • 商当前位 = 0
    • 左移1位,带入被除数下一位(若还有)
  4. 结束

    • 最终剩下的 ( n-1 ) 位即为 余数
    • 商可选记录(多数应用如 CRC 不需要)

🧪 示例1:1101 ÷ 101商无0

步骤 当前窗口 最高位 操作 商位 XOR结果 带入下一位
1 110 1 XOR 101 1 011 带入 10111
2 111 1 XOR 101 1 010

✅ 商 = 11,余数 = 10

💡 两次窗口最高位都是1 → 商全是1,没有0

💡 模2除法的"窗口"是动态对齐到当前最高位的1,不是固定从左到右逐位判断!

  • 你可能误以为中间出现的 011 中的"0"需要"跳过",但实际上:
    • 那个 0 是XOR结果的一部分,不是"新的被除数起始位"
    • 我们不会对每一位单独判断是否跳过,而是:
    • 每次看当前3位窗口的最高位是否为1
    • 在第二步,窗口是 111(不是 011),所以不需要跳过,直接XOR,商写1

🧪 示例2:1001 ÷ 101商有0

步骤 当前窗口 最高位 操作 商位 XOR结果 带入下一位
1 100 1 XOR 101 1 001 带入 10011
2 011 0 不XOR 0 011

✅ 商 = 10,余数 = 11

💡 第二步窗口是 011,最高位为0 → 商写0,跳过XOR


🔑 关键要点总结

问题 正确认知
"跳过"是什么意思? 当前窗口最高位为0 → 商0,不执行XOR,直接移位
商是否存在? 存在!每一步都有一位商(1 或 0),但 CRC 中通常忽略
余数长度? 总是 = 除数长度 − 1(如除数3位 → 余数2位)
是否逐位判断? 否!是按 与除数等长的窗口 判断最高位
前导0怎么处理? 窗口包含前导0,但只看该窗口的最高位决定是否XOR

📝 一句话口诀(便于记忆)

"对齐除数看头位,是1就XOR商写1,是0跳过商写0,移位带入继续算。"


4.普通算术除法

🔥 经典借位场景:100 ÷ 3

我们一步步手算,并高亮借位发生的位置

第一步:列竖式
复制代码
      ??
    ------
3 ) 1 0 0
  • 3 不能整除 1(百位),所以看前两位:10

  • 10 ÷ 3 = 3(因为 3×3=9 ≤ 10)

  • 商的第一位是 3,写在十位上

    复制代码
        3
      ------

    3 ) 1 0 0
    - 9 ← 3 × 3 = 9
    -----

第二步:做减法 10 − 9
复制代码
   1 0
−    9
-------
  • 个位:0 − 9 → 不够减!
  • 向十位借1
  • 十位的1变成0,个位得到10
  • 计算:10 − 9 = 1

这里发生了借位!

结果是 1 ,然后把被除数的下一位 0 移下来,变成 10

复制代码
      3
    ------
3 ) 1 0 0
    - 9
    -----
      1 0   ← 余1,带下0 → 10
第三步:10 ÷ 3 = 3(3×3=9)
复制代码
      3 3
    ------
3 ) 1 0 0
    - 9
    -----
      1 0
    -   9
    -----
        1   ← 余数

再做一次减法:10 − 9

→ 又一次:0 − 9 不够,向十位借1 → 再次借位


✅ 完整过程(标出借位)

复制代码
       3 3
     ------
3 ) 1 0 0
    - 9      ← 3×3
    -----
  → ¹0        ← 十位1借给个位,自己变0,个位变成10
     1 0      ← 实际是 (10−9)=1,带下0 → 10
    - 9
    -----
  → ¹0        ← 再次借位!
       1      ← 余数

💡 每次计算 10 − 9 时,个位0不够减9,必须向十位借1 ,这就是带借位


📌 关键点总结

步骤 发生了什么 是否借位
10 − 9 个位 0 < 9 → 向十位借1 ✅ 是
10 − 9(第二次) 同样,个位0 < 9 → 借1 ✅ 是

在十进制中,借1当10,所以 0 借位后变成 10,就能减了。


✅ 最终结果

  • :33
  • 余数:1
  • 验证:( 3 \times 33 + 1 = 99 + 1 = 100 ) ✅

🔁 对比记忆

  • 普通算术除法

    • 减法要借位(如 0 − 9 → 借1变10 − 9 = 1)
    • 是我们小学学的"标准除法"
  • 模2除法(用于CRC):

    • 减法 = 异或(XOR)
    • 0 − 1 = 1(因为 0 ⊕ 1 = 1),永远不需要借位

💬 一句话记住

"普通除法中的借位,就是你算 100 ÷ 3 时,每次 10 减 9 都要从十位'借1当10'的那个动作。"

5.CRC

循环冗余校验码(Cyclic Redundancy Check,CRC)

6.海明码

6.1 校验码

已知原始信息数据为 1011,海明码校验码
1. 确定校验位个数

设原始数据位数 ( m = 4 )(即 1011)。

海明码要求满足 ( 2^r \ge m + r + 1 ) 来确定校验位个数 ( r )。

  • ( r = 2 ) 时:( 4 + 2 + 1 = 7),(2^2 = 4) 不够。
  • ( r = 3 ) 时:( 4 + 3 + 1 = 8),(2^3 = 8) 刚好满足。

所以 校验位 ( r = 3 ),总位数 ( n = m + r = 7 )。


2. 确定校验位的位置

校验位 ( P_1, P_2, P_4 ) 放在 ( 2^{i-1} ) 的位置(即位置 1、2、4,从 1 开始数位置)。

位置编号与对应位的关系(P 表示校验位,D 表示数据位):

位置 7 6 5 4 3 2 1
D4 D3 D2 P3 D1 P2 P1

原始数据 1011 按顺序 ( D_4 D_3 D_2 D_1 ) 填入 ( D4, D3, D2, D1 ):

  • ( D4 = 1 )
  • ( D3 = 0 )
  • ( D2 = 1 )
  • ( D1 = 1 )

暂时校验位未知(记为 P1, P2, P3),我们得到:

位置 7 6 5 4 3 2 1
1 0 1 P3 1 P2 P1
位置 二进制(从右数位 1,2,4 对应权值 1,2,4) 存放的位
1 001 P1
2 010 P2
3 011 D1=1
4 100 P3
5 101 D2=1
6 110 D3=0
7 111 D4=1

3. 确定每个校验位的奇偶校验组(偶校验)
P1(位置 1) 校验的位:位置 1、3、5、7 的二进制 最低位为 1

即:1(1), 3(3=011), 5(5=101), 7(7=111) → 对应位 P1, D1, D2, D4。

P_1 \\oplus D1 \\oplus D2 \\oplus D4 = 0

P_1 \\oplus 1 \\oplus 1 \\oplus 1 = 0

P_1 \\oplus 1 = 0 \\quad \\Rightarrow \\quad P_1 = 1

(因为 ( 1 \oplus 1 = 0 ))


P2(位置 2) 校验的位:位置 2、3、6、7 的二进制 次低位为 1

即:2(010), 3(011), 6(110), 7(111) → 对应位 P2, D1, D3, D4。

P_2 \\oplus D1 \\oplus D3 \\oplus D4 = 0

P_2 \\oplus 1 \\oplus 0 \\oplus 1 = 0

P_2 \\oplus 0 = 0 \\quad \\Rightarrow \\quad P_2 = 0


P3(位置 4) 校验的位:位置 4、5、6、7 的二进制 第三位为 1

即:4(100), 5(101), 6(110), 7(111) → 对应位 P3, D2, D3, D4。

P_3 \\oplus D2 \\oplus D3 \\oplus D4 = 0

P_3 \\oplus 1 \\oplus 0 \\oplus 1 = 0

P_3 \\oplus 0 = 0 \\quad \\Rightarrow \\quad P_3 = 0


4. 填入校验位得到完整海明码

P1=1,P2=0,P3=0。

位置:

1 → 1

2 → 0

3 → D1=1

4 → P3=0

5 → D2=1

6 → D3=0

7 → D4=1

得到:位置 7~1 为 1 0 1 0 1 0 1(注意通常书写顺序按位置 1 在最右)

从高到低(位置 7 到 1)的二进制是:1010101


5. 最终答案

原始数据 1011,海明校验码(7 位)为:

\\boxed{1010101}

其中校验位是 ( P_1 = 1, P_2 = 0, P_3 = 0 ),放在总码的位置 1、2、4。

我们具体看一下这一步的详细推导。


海明码的偶校验 是一种保证特定校验组内"1"的个数为偶数的机制。

具体来说:


6.2 海明码中的偶校验和奇校验

1. 偶校验(Even Parity)

对于一组二进制位,偶校验位设置成 0 或 1 ,使得这组数据位加校验位中 "1"的总数 为偶数。

例如:

  • 数据 101 → "1"的个数 = 2(偶数),则校验位 = 0,保持偶数。
  • 数据 111 → "1"的个数 = 3(奇数),则校验位 = 1,使总数变成 4(偶数)。

校验方程:

P \\oplus D_1 \\oplus D_2 \\oplus \\dots \\oplus D_k = 0

(即所有位异或结果为 0)


2. 海明码中的偶校验应用

在海明码中,每个校验位负责一组不同的数据位。分组规则是根据位置的二进制编号来划分的。

对于长度为 ( n ) 的海明码(( n = m + r )),位置从 1 到 ( n ) 编号,校验位放在 ( 2^{i-1} ) 的位置(即 1、2、4、8...)。

校验位 ( P_k )(在位置 ( 2^{k-1} ))负责校验所有位置编号二进制表示中,第 ( k ) 位(从右数,最低位是第 1 位)是 1 的那些位置

例子(7 位海明码,r=3)

  • ( P_1 )(位置 1):二进制最低位是 1 的位置 → 1, 3, 5, 7
  • ( P_2 )(位置 2):二进制第二位是 1 的位置 → 2, 3, 6, 7
  • ( P_4 )(位置 4):二进制第三位是 1 的位置 → 4, 5, 6, 7

对每个校验组分别进行偶校验,得到一个方程,解出该校验位的值。


3. 偶校验的作用

在发送端,校验位按偶校验规则计算填入。

在接收端,重新计算每个校验方程,如果全部为 0,则无错;如果有方程不为 0,将这些方程的校验位位置值组合成一个二进制数,就指示出错的位置。

这是因为偶校验组重叠覆盖了每一个位,任何单个位置错误都会影响一组特定的校验方程,从而唯一确定出错位。


4. 与奇校验的区别
  • 偶校验:组内异或结果 = 0
  • 奇校验:组内异或结果 = 1
    海明码常用偶校验(教材标准做法),但奇校验原理类似,只是方程右边为 1。

所以简单说:
海明码的偶校验 = 将数据位和校验位按特定规则分组,每组内通过设置校验位使得"1"的个数为偶数,以便检错与纠错。

判断数据位由哪些校验码校验,规则如下:


6.3.数据位由哪些校验码校验

在海明码中,每一个数据位的位置编号(从 1 开始数) 的二进制形式中,如果某一位是 1,那么它就受到对应权值的校验位的校验。

校验位的位置是 ( 2^{k-1} ):

  • 校验位 ( P_1 ) 在位置 ( 1 = 2^{0} )(二进制 001) → 负责最低位为 1 的所有位置
  • 校验位 ( P_2 ) 在位置 ( 2 = 2^{1} )(二进制 010) → 负责第二位为 1 的所有位置
  • 校验位 ( P_3 ) 在位置 ( 4 = 2^{2} )(二进制 100) → 负责第三位为 1 的所有位置
    ......依此类推。

1. 判断方法
步骤 1:给数据位位置编号(整个海明码的位置)

假设我们有一个 7 位海明码(4 数据位 + 3 校验位),位置从 1 到 7:

位置 7 6 5 4 3 2 1
存放 D4 D3 D2 P3 D1 P2 P1

数据位 ( D_1 ) 在位置 3,( D_2 ) 在位置 5,( D_3 ) 在位置 6,( D_4 ) 在位置 7。


步骤 2:将数据位的位置编号转换成二进制(用 r 位)

这里 r=3,二进制用 3 位(因为校验位位置是 1,2,4,对应二进制位 1,2,3 从右数)。

  • ( D_1 ) 位置 3 → 二进制 011

    • 最低位是 1 → 受 P1 校验
    • 第二位是 1 → 受 P2 校验
    • 第三位是 0 → 不受 P3 校验
      所以 ( D_1 ) 由 P1 和 P2 校验。
  • ( D_2 ) 位置 5 → 二进制 101

    • 最低位是 1 → 受 P1 校验
    • 第二位是 0 → 不受 P2 校验
    • 第三位是 1 → 受 P3 校验
      所以 ( D_2 ) 由 P1 和 P3 校验。
  • ( D_3 ) 位置 6 → 二进制 110

    • 最低位是 0 → 不受 P1 校验
    • 第二位是 1 → 受 P2 校验
    • 第三位是 1 → 受 P3 校验
      所以 ( D_3 ) 由 P2 和 P3 校验。
  • ( D_4 ) 位置 7 → 二进制 111

    • 最低位是 1 → 受 P1 校验
    • 第二位是 1 → 受 P2 校验
    • 第三位是 1 → 受 P3 校验
      所以 ( D_4 ) 由 P1、P2、P3 全部校验。

2. 总结公式

对于位置编号 ( pos )(二进制表示),如果二进制从右数第 ( k ) 位(k 从 1 开始)是 1,则该校验位 ( P_k )(位置 ( 2^{k-1} ))会校验该数据位。

更简单的记忆法:
将数据位的位置编号分解成 2 的幂次和,幂次对应的校验位就是它受的校验

例:

  • ( 3 = 1 + 2 ) → P1、P2
  • ( 5 = 1 + 4 ) → P1、P3
  • ( 6 = 2 + 4 ) → P2、P3
  • ( 7 = 1 + 2 + 4 ) → P1、P2、P3

3. 反过来:校验位校验哪些位置?

2^{i} i=0,i=1,i=2... 1(001),2(010),4(100),8(1000),16(10000)

校验位 P1(位置 1)校验所有二进制最低位为 1 的位置。

校验位 P2(位置 2)校验所有二进制第二位为 1 的位置。

校验位 P4(位置 4)校验所有二进制第三位为 1 的位置。

校验位 P4(位置 8)校验所有二进制第四位为 1 的位置。

这样就可以从数据位位置反推出由哪些校验位校验,也可以从校验位知道它覆盖了哪些数据位。

6.4.海明码的检错和纠错原理

海明码的检错和纠错原理 基于多个奇偶校验位(偶校验)对数据位进行重叠分组,使得任何单个比特错误会影响一组特定的校验方程,从而唯一确定错误位置。


1.核心思想
  1. 冗余位(校验位):插入 ( r ) 个校验位到数据位中,总长度 ( n = m + r )。
  2. 分组校验:每个校验位负责一组特定的数据位(包括其他某些校验位)。
  3. 重叠覆盖:每一个数据位至少属于两个不同的校验组。
  4. 定位错误 :单个比特出错会破坏它所在的所有校验组的偶校验条件,这些被破坏的校验组的编号组合起来就唯一对应出错的位置。

2.编码过程(复习)

假设数据位 ( D_4 D_3 D_2 D_1 = 1011 ),求海明码(7,4):

  1. 确定校验位个数 ( r ),满足 ( 2^r \ge m + r + 1 )(这里是 3)。

  2. 校验位放在位置 ( 1, 2, 4 )(即 ( 2^{k-1} ))。

  3. 位置分配:

    位置:7 6 5 4 3 2 1

    存放:D4 D3 D2 P3 D1 P2 P1

    填入数据位:D4=1, D3=0, D2=1, D1=1。

  4. 计算校验位(偶校验):

  • P1(校验位置 1,3,5,7):P1 ⊕ D1 ⊕ D2 ⊕ D4 = 0 → P1=1
  • P2(校验位置 2,3,6,7):P2 ⊕ D1 ⊕ D3 ⊕ D4 = 0 → P2=0
  • P3(校验位置 4,5,6,7):P3 ⊕ D2 ⊕ D3 ⊕ D4 = 0 → P3=0

得到海明码:位置 7~1 → 101 0 1 0 11010101


3.检错与纠错过程(接收端)
1. 重新计算校验方程

收到一个 7 位码字,按同样分组计算偶校验结果,得到校验子(Syndrome) ( S_3 S_2 S_1 ):

\\begin{cases} S_1 = P_1 \\oplus D_1 \\oplus D_2 \\oplus D_4 \\quad (\\text{应为 0,若为 1 则本组有错}) \\ S_2 = P_2 \\oplus D_1 \\oplus D_3 \\oplus D_4 \\ S_3 = P_3 \\oplus D_2 \\oplus D_3 \\oplus D_4 \\end{cases}

注意:这里的 ( P_1, D_1 ) 等是从接收到的码字中取对应位置的值。

2. 校验子含义
  • 如果 ( S_3 S_2 S_1 = 000 ) → 无错(或不可检测的多错,海明码只能保证检测并纠正 1 位错)。
  • 如果 ( S_3 S_2 S_1 \neq 000 ),则它是一个二进制数,直接指出出错的位置编号。

为什么?

因为每个位置的编号二进制形式对应它会影响哪些校验组(S1 对应最低位,S2 对应第二位,S3 对应第三位)。

例子

  • 假设 D2(位置 5)出错:
    位置 5 二进制 101 → 影响 P1(最低位)和 P3(第三位),不影响 P2。
    所以:
    ( S_1 = 1 )(P1 组偶校验破坏)
    ( S_2 = 0 )
    ( S_3 = 1 )
    校验子 ( S_3 S_2 S_1 = 101 )(二进制)→ 十进制 5,正好是出错位置。

3. 纠错

得到校验子 ( S = (S_3 S_2 S_1)_2 ),转十进制得到出错位置。

将该位置的比特取反(0→1 或 1→0),即完成纠正。


4. 举例验证

发:1010101

收:假设位置 5 由 1 错成 0,收到 1000101

重新计算校验子:

位置 7(D4)=1, 6(D3)=0, 5(D2)=0, 4(P3)=0, 3(D1)=1, 2(P2)=0, 1(P1)=1。

  • ( S_1 = P1 ⊕ D1 ⊕ D2 ⊕ D4 = 1 ⊕ 1 ⊕ 0 ⊕ 1 = 1 ⊕ 1 = 0 ⊕ 1 = 1 )
    (仔细算:1⊕1=0, 0⊕0=0, 0⊕1=1 → 最终 S1=1)

其实更清楚列式:

P1 组包含位置 1(P1=1), 3(D1=1), 5(D2=0), 7(D4=1)

1 的个数:1(P1)是1, 3(D1)是1, 5(D2)是0, 7(D4)是1 → 1 的个数 = 3(奇数)→ 偶校验破坏 → S1=1。

  • ( S_2 = P2 ⊕ D1 ⊕ D3 ⊕ D4 )

    位置 2(P2=0), 3(D1=1), 6(D3=0), 7(D4=1)

    1 的个数:D1=1, D4=1 → 两个 1(偶数),P2=0 不影响,所以总共 1 的个数=2(偶数)→ 偶校验满足 → S2=0。

  • ( S_3 = P3 ⊕ D2 ⊕ D3 ⊕ D4 )

    位置 4(P3=0), 5(D2=0), 6(D3=0), 7(D4=1)

    1 的个数:1(奇数)→ S3=1。

所以 ( S_3 S_2 S_1 = 101 ) → 十进制 5 → 位置 5 错。

纠正:位置 5 的 0 改为 1 → 恢复为 1010101。


4.检错能力
  • 可纠正 1 位错(因为校验子 000 表示无错,其它 ( 2^r - 1 ) 种非零值对应 n 位中的某一位错,这里 ( n \le 2^r - 1 ))。
  • 可检测 2 位错(校验子非零,但无法唯一确定是哪两位错,因为校验子模式与错误图样不再是一一对应,只能发现错误但不能纠正)。
  • 不能可靠检测 ≥3 位错(可能校验子又变回 000 而漏检)。

相关推荐
Mysticbinary2 年前
校验码原理介绍
身份证·校验码·check digit