MitseaBlog/content/post/126cc71ce5234e699042036798edcf66/index.zh-cn.md
FlintyLemming b6f5b620fd Add slug
2022-09-23 16:52:31 +08:00

87 lines
7.2 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

+++
author = "FlintyLemming"
title = "海明校验码"
slug = "126cc71ce5234e699042036798edcf66"
date = "2020-06-01"
description = ""
categories = ["Coding"]
+++
在了解海明校验码之前,需要知道一个重要的概念——码距。
## 概念介绍-码距
码距是指是两个码字中不相同的二进制位的个数举个例子有两个编码分别是01101101和01000101可以发现这两个编码有两位值不相同所以他们的码距为2。
那么你还有可能听到这么一个说法“8421码码距d=1”这里的码距指的是“该数据编码的最小码距”是整个编码系统中中任意两个码字的码距的最小值。还有一个问题使用四位二进制的编码系统码距一定是1吗显然不是虽然用的是四位二进制编码系统但是没有限定编写什么码字。如果我用这个编码系统只编写0000、0011、0101这三个码字那么这个编码系统的码距就是2因为这三个码子互相之间的码距最小值为2。
## 码字的结构
接下来我还要介绍一下添加校验码后整个码字的结构。码字包括信息位和校验位这里设信息位的位数为k校验位的位数为r那么整个码字的长度就是k+r。
## 所需校验位的计算
对于校验位来说,需要有足够的位数来表示信息位中发生的错误,而海明校验码只表示信息位中一位的错误。
举个例子并不是海明码的结构不严谨仅作理解现在有信息位0110那么校验位就需要有四个状态分别表示信息位的第一、二、三或者第四位有误。那么校验位如果只有一位0和1并不能表示四种状态。我们试试两位比如校验位我用00表示信息位第一位发生错误01表示第二位发生错误用10表示第三位发生错误11表示第四位发生错误。看似没有问题但是忘了一点校验位如何表示信息位没有错误呢所以其实我们需要4+1=5种情况来表示信息位的校验信息即需要3位的校验位。
而对于海明码来说,数据位和校验位穿插,存在校验位可以“我 查 我 自 己”的情况需要检查的位数就是k+r。所以对于k位的信息位r位的校验位需要满足2^r-1>k+r才能检查出1个位的错误。
## 确定校验码和数据的位置
上节提到海明码的校验位和信息位是穿插的所以我们需要确定校验位的各个位置。为了方便说明我们给校验码定义为P1、P2、P3…数据为定义为D1、D2、D3…最终整个码字的编码依次为M1、M2、M3……那对于校验码Pi来说它的位置是M[2^(i-1)]比如P1的位置是M1、P2的位置是M2P3的位置是M4P4的位置是M8……那么剩下的就是数据的位置
M1    M2    M3    M4    M5    M6    M7    M8    M9
P1    P2     D1    P3     D2    D3     D4    P4     D5
## 求出校验位的值(规律法)
这里以一个例子讲解,比如我们现在掌握如下信息
M1    M2    M3    M4    M5    M6    M7    M8    M9    M10
P1    P2     D1    P3     D2    D3      D4    P4    D5     D6
(空)    (空)    1    (空)    0        1         1    (空)    0        1
表里可以看出已经给定了一组信息位的值现在我们先计算P1的值
我们从**P1开始连续1个中间间隔1个再连续1个**,组合成一个串:
【为了方便理解我详细说一下上方加粗的过程从P1也就是对应的M1开始连续一个就还是P1然后间隔一个就跳过M2再连续一个取M3的值然后间隔一个也就是跳过M4再连续一个取M5的值…以此类推我们取了P1、3、5、7…的值把它放在一个串里】
然后对这个串进行偶校验也就是说保证这个串中1的个数为偶数个可以看到已经有两个1了所以我们在第一位补0
这也就是我们得到的P1的值
为了加强理解我们再计算一下P2的值
我们**从P2开始连续2个中间间隔2个再连续2个**,组合成一个串:
【为了方便理解我再详细说一下加粗部分的过程从P2也就是对应的M2开始连续两个就是M2、M3取M3的值然后间隔2个跳过M4、M5再连续两个取M6、M7的值再间隔两个跳过M8、M9再连续两个取M10、M11…以此类推我们取了M3、6、7、10的值】
然后同样进行偶校验发现已经有4个1所以补0
这也就是我们得到的P2的值
同理计算P3的过程中我们**从P3开始连续3个中间间隔3个再连续3个**也就是取M4、5、6跳过M7、8、9取M10、11、12
然后进行偶校验补0
P4同理最后补的是1
这样我们就依次获得了校验位的数据P1-4依次为0、0、0、1
## 求出校验位的值(数学法)
还是用这一题:
第一步我们要列出整个码字的编码对应的二进制。比如M11对应的就是0001M2就是0010M3就是0011
观察这个二进制编码以M3为例0011第一位和第二位都是1那么我们称M3和P1、P2有关
第二步我们要找到还有哪些和P1有关可以发现M1、3、5、7、9都和P1有关
第三步以此类推找出哪些和P2有关可以找到M2、3、6、7、10哪些和P3有关……
第四步去掉第一位因为比如对于P1来说M1、3、5、7、9中M1并没有值列出如下方程式
P1 = M3 ⊕ M5 ⊕ M7 ⊕ M9 = 1 ⊕ 0 ⊕ 1 ⊕ 0 = 0
P2 = M3 ⊕ M6 ⊕ M7 ⊕ M10 = 1 ⊕ 1 ⊕ 1 ⊕ 1 = 0
P3 = M5 ⊕ M6 ⊕ M7 = 0 ⊕ 1 ⊕ 1 ⊕ = 0
P4 = M9 ⊕ M10 = 0 ⊕ 1 = 1
便可以算出校验位的值
## 接收端校验
参考上一节求出校验位的值数学法中求P的过程我们需要把P和其相关的数据位相加比如上面我们计算了P1 = M3 ⊕ M5 ⊕ M7 ⊕ M9 = 1 ⊕ 0 ⊕ 1 ⊕ 0 = 0这里我们就校验P1 ⊕ M3 ⊕ M5 ⊕ M7 ⊕ M9 是否等于 0接着依次计算P2 ⊕ M3 ⊕ M6 ⊕ M7 ⊕ M10、P3 ⊕ M5 ⊕ M6 ⊕ M7、P4 ⊕ M9 ⊕ M10是否都等于0如果都是0说明这个数据没有问题。
如果出问题了呢?下面举个例子:
还是上面那一题如果M5在传输中发生错误0变成了1
那么计算中就会发现:
P1 ⊕ M3 ⊕ M5 ⊕ M7 ⊕ M9 = 1
P2 ⊕ M3 ⊕ M6 ⊕ M7 ⊕ M10 = 0
P3 ⊕ M5 ⊕ M6 ⊕ M7 = 1
P4 ⊕ M9 ⊕ M10 = 0
得出出错位为0101(2)位即第五位那么只要把M5的值反转即可得到正确的字串。
## 海明码的码距
回到一开始说的码距问题有题目会问海明码的码距是多少答案是3。为什么呢其实我们不妨再观察一下用数学法计算校验位的过程
P1 = M3 ⊕ M5 ⊕ M7 ⊕ M9 = 1 ⊕ 0 ⊕ 1 ⊕ 0 = 0
P2 = M3 ⊕ M6 ⊕ M7 ⊕ M10 = 1 ⊕ 1 ⊕ 1 ⊕ 1 = 0
P3 = M5 ⊕ M6 ⊕ M7 = 0 ⊕ 1 ⊕ 1 ⊕ = 0
P4 = M9 ⊕ M10 = 0 ⊕ 1 = 1
不难发现即使是靠前的数据位比如M3、M5都至少与两个校验位有关所以变了一个数据位会更改两个校验位一共改变三个值。即可得出海明码的码距为3。