写在前面:大家好K。首先为你点进这篇有趣的文章点赞👍!文章在撰写过程中难免有疏漏和错误,欢迎你在下方留言指出文章的不足之处;如果觉得这篇文章对你有用,也欢迎你点赞和留下你的评论。更多内容请点进👉我的博客K。👈阅览。
文章目录
1. 什么是奇偶校验法?
- 偶校验
一串01数字串中,如果有偶数个1,则表明这串数字是正确的,没有在传输过程中出错。
- 奇校验
一串01数字串中,如果有奇数个1,则表明这串数字是正确的,没有在传输过程中出错。
缺点:奇偶校验只能在错一位时发现有错,如果同时错两位(或偶数位),这没办法校验出来。
但是同时多位出错的情况很少发生,所以奇偶校验法得到广泛应用。
例:
偶校验:如果你想要传输0101
,传输前在开头加一位校验位0
,这样传输的是00101
,此时这串数有2个1
,符合偶校验。
奇校验:如果你想要传输0101
,传输前在开头加一位校验位1
,这样传输的是10101
,此时这串数有3个1
,符合奇校验。
本文用偶校验法讲解汉明码
2. 非代码,通俗理解汉明码原理
现在不要管前面讲的,这是全新的东西。
假设现在要传输一个数有7位,位号为1、2、3、4、5、6和7。它们有如下关系:
-
现在我们假设:这7位数中一定有一位是错的,而1号位所在大圈和4号位所在大圈一定是正确的,=>推得错的这一位一定是2号位;
-
再假设:这7位数中一定有一位是错的,而2号位所在大圈是正确的,且1号位和4号位所在大圈同时出错了,=>那么错的这一位一定是5号位;
-
同理,再假设:这7位数中一定有一位是错的,而此时所有大圈都出错了,=>那么错的这一位一定是7号位。
通过上面三个假设我们我们可以看到,我们都是以大圈为单位,根据三个大圈的出错情况(无错、1个错、2个错、3个全错)就可以推得到底是哪一位出错了。我们称第1、2、4号位为校验位。
3. 汉明码如何分组、编码?
通过上面的简化例子可以发现,要实现上面的校验过程,有两步一定要做:1. 分组(上面的每个大圈为一组);2. 每组都有一个校验位(即上面的1、2和4号位)。那么具体是如何做的呢?
3.1 如何确定校验位?
我们先把1~7的二进制写出来,再看看每个二进制数的1
在哪里:
1:0001 >>> XXX1('1'在第1号位)
2:0010 >>> XX1X('1'在第2号位)
3:0011 >>> XXX1、XX1X('1'在第1、2号位)
4:0100 >>> X1XX('1'在第3号位)
5:0101 >>> XXX1、X1XX('1'在第1、3号位)
6:0110 >>> XX1X、X1XX('1'在第2、3号位)
7:0111 >>> XXX1、XX1X、X1XX('1'在第1、2和3号位)
我们可以看到只有1个1
的位号(1、2和4号位)都是2n(20、21和22)。汉明码把这样2n号位作为校验位(上节中的大圈),这些位上的数称为校验码。
3.2 如何分组?
我们通过举例子来说明。哪些位号应该和1号位
组成一组呢(画大圈)?
答:1号位1
的位置在第1位,形如XXX1
,那么位号分解出来有XXX1
的位,会和1号位一组。这里第3、5和7号位与1号位一组;
同理,2号位1
的位置在第2位,形如XX1X
,那么位号分解出来有XX1X
的位,会和2号位一组。这里第3、6和7号位与2号位一组。
4号位的分组亦同理易得。
3.3 汉明码如何编码?
通过上两小节,我们知道了如何确定校验位和如何分组,那么该如何将原始数据编码成汉明码呢?
我们也通过例子来说明。我们现在给0101
编码。
我们先写成这种形式:_ _ 0 _ 1 0 1
。留的空白就是校验位(2n号位)。
且第1、3、5和7号位为一组(_ 0 1 1),第2、3、6和7号位为一组(_ 0 0 1),第4、5、6和7号位为一组(_ 1 0 1)。
前面说过,本文以偶校验法来讲解汉明码。现在以组为单位(大圈),看看每组的校验位_
都填啥。显然,第1号位填0
,第2号位填1
,第4号位填0
。使得每组的1
的个数为偶数。
所以对于0101
,编码后得到的汉明码为0100101
。
偶校验码的计算机生成由异或操作实现。如第一组的校验码
0
实际由该组其他位上的数0⊕1⊕1
。奇校验码由同或操作实现。
4. 数学关系
我们可以发现,上面示例中有3个校验位,可以校验最多7位数(3个校验码+4个原始数据)。
即有k位校验位,最多可以得到有2k-1位数的汉明码:
2k-1 >= k+n(n为原始数据的位数)
5. 如何知道哪位错了?(检错方法)
提醒:依旧是在易错1位的基础上讨论
我们按照分组方法,将接收到的一串汉明码同样分成几组。手动计算每组信息是否与校验码匹配,再画大圈找到错的那一位数。昂?是这样吗?P!
当接收到的位数很多时,肯定不能手动计算出错位,画大圈都要画成憨憨。事实上,汉明码有一种非常快速的找到错位的方法。
继续上面的例子,我们发送的汉明码为0100101
,但是接收到的数为0101101
。我们以接收者的角度来说,乍一看并不能确定哪一位是错的(只能错一位),但是这是优秀的汉明码啊!大哥!看看怎么找出错位来的吧!
我们将0101101
按分组方法分成三组(注意三组按校验位从小到大写):
第一组:0011,校验正确,标记为0
第二组:1001,校验正确,标记为0
第三组:1101,校验错误(偶校验这里校验位应为0才能保证这组'1'的个数为偶数),标记为1
将标记倒序写出来是100
,写成十进制数为4
,所以这串数字的第4位出错了,应该反过来为0
。由此可以确定接收到的0101101
是错误的,正确串应该是0100101
。
这个方法口诀为正确标0错标1,分组校验倒叙查。