能将0和1两个数字玩的如此传神!是个程序要都应该了解的海明码(通俗版)

得到海明码步骤:


一、确定校验码的位数k

二、确定校验码的位置

三、数据的位置

四、求出校验位的值

其中还需要一个公式的推导,好了,下面开始:

首先,海明码的作用是:在编码中如果有错误,可以表达出第几位出了错,二进制的数据只有0和1,修改起来很容易,求反即可,这需要加入几个校验位。对于一个m位的数据信息,到底应该加入几个呢?假设需要k个,那么编码之后应该是m+k位,这k个二进制数组成的数据能够表达的数值是2的k次方个,比如需要3个校验位,k=3,3位二进制数从000
、 001 、……
、111共有8个数值,而这m+k个二进制组成的数据的所有编码中,只有一个是正确的,其他的都是表达了错误的位置信息的,所以2的k次方个编码中去掉正确的那一个,也就是(2的k次方-1),如果这个数值等于m+k,就可以完全表达出出错的位置了,(2的k次方-1)也可以大于m+k,

比如:给10个学员进行编号,可以用一位数来编码:学号为0 、1 、2 、3 、……、9 ,也可以 用两位数或者五位数,00000 、00001
、00002 、……、00009,但是没有必要用五位呀,只要能满足编码的要求就可以了,所以说我们求出满足条件的最小的k值就可以!

下面举例说明:我们要推导出D= 101101这个数字的海明码

一、确定校验码的位数k

数据的位数m=6,按照上面我们说的公式来计算满足条件的k的最小值

2的k次方-1>=m+k

即:2的k次方-1>=6+k

解此不等式得:满足不等式的最小k=4,也就是D=101101这个数字的海明码应该有6+4=10位,其中原数据6位,校验码4位。

二、确定校验码的位置

设这4为校验码分别为P1、P2、P3、P4

数据从左到右为D1、D2、……、D6

编码后的数据共有6+4=10位,设为M1、M2、……M10

校验码Pi(这里i=1,2,3,4)在编码中的位置为2的(i-1)次方,值是这样的1,2,4,8,16……即:P1在M1位置,P2在M2位置,P3在M4位置,P4在M8位置,这里一共有10位,所以排不到M16,见图中“甲”行红色字体







































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

图1

三、数据的位置

这个很简单,除了校验码的位置其余的就是数据的位置,填充进去就可以了,见图中“甲”行的蓝色字体,于是可以先把数据信息填进去,见“丙”行,下面就是最关键的部分,求出校验位的值啦!!!

四、求出校验位的值

这里会用到一个公式,找了好多资料都说了这个公式,但是完全没有必要死记硬背,是有规律的,回顾一下二进制的表达,对于一个4位二进制数,可以表达16个值,0000B~1111B,“B”代表二进制,“D”代表十进制,假定这4位二进制数,从左到右分别为S4、S3、S2、S1,请把脑袋向左歪90°看下图:1D=0001B,所以M1在S1那一行,4D=0100B,所以M4在S3那一行,5D=0101B,这就不能用一个格子来表达了,所以需要S3和S1共同表达,即4+1=5,看图中黄色的部分,是不是M5?看出规律了吧?M后边的数字都可以拆为由2的n次方的数相加来表达,在举一个例子M7:4+2+1=7即:7D=0111B,看图中橙色的部分,都是M7吧!by
the
way:这个公式在验证纠错的时候还会用得到,我找的网上的很多资料写了好几个公式,看后完全“懵懂”了,其实只需要这一个就可以了,按照我说的这个方法,你只要记住这个公式的推导就可以解决所有问题了,怎么样?强大吧?


















































S1

=

M1

M3

M5

M7

M9

S2

=

M2

M3

M6

M7

M10

S3

=

M4

M5

M6

M7



S4

=

M8

M9

M10





图2

接下来就是代入求值的过程了,不要说你不懂“⊕”这个符号哦!这是异或,真不懂的话,就去搜吧!按照图1中的指示,把相应的值代入到图2
的公式里,可以得到如下内容

S1=M1⊕M3⊕M5⊕M7⊕M9      =P1⊕D1⊕D2⊕D4⊕D5

S2=M2⊕M3⊕M6⊕M7⊕M10    =P2⊕D1⊕D3⊕D4⊕D6

S3=M4⊕M5⊕M6⊕M7             
=P3⊕D2⊕D3⊕D4

S4=M8⊕M9⊕M10                   
=P4⊕D5⊕D6

如果海明码没有错误信息,S1、S2、S3、S4都为0,等式右边的值也得为0,由于是异或,所以Pi(i=1,2,3…)的值跟后边的式子必须一样才能使整个式子的值为零,即:Pi=后边的式子的值,即:

P1  =   D1  ⊕  D2  ⊕  D4  ⊕ 
D5

P2  =   D1  ⊕  D3  ⊕  D4  ⊕ 
D6

P3  =   D2  ⊕  D3  ⊕ 
D4

P4  =   D5  ⊕ 
D6

懂了吗?是不是说的有点跨度?仔细想一下异或的含义,以S4=
P4⊕D5⊕D6为例,S4=0,就是说P4⊕D5⊕D6=0,那么P4和(D5⊕D6)必须一样(即P4=
D5⊕D6),那么异或的结果才能为零吧?!!不要以算术加减法来理解,要用逻辑数学的思维啦!!

那么可以算出Pi的值了吧?

P1   =     D1   ⊕   
D2   ⊕    D4   ⊕   
D5   =     1    
⊕    0     ⊕   
1     ⊕    0    
=     0

P2   =     D1   ⊕   
D3   ⊕    D4   ⊕   
D6   =     1    
⊕    1     ⊕   
1     ⊕    1    
=     0

P3   =     D2   ⊕   
D3   ⊕   
D4                
=     0     ⊕   
1     ⊕   
1                  
=     0

P4   =     D5   ⊕   
D6                              
=     0     ⊕   
1                                
=     1

恭喜你,大功告成,把Pi的值填写到图1中,看“丙”行,就可以得到haimming编码啦!哈哈!



















































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

0

0

1

0

0

1

1

1

0

1

五、海明码校验过程

现在我们得到了D=101101的正确海明码就是













0

0

1

0

0

1

1

1

0

1

那么出错的时候是怎么验证出来的呢?比如第5位错了,第5位现在的值是0,如果错了,它只能是1,二进制就这两种值即:我们得到了这样的一组编码,现在要找出错误的位置(假定你不知道哪里错了啊!!!)
























M1

M2

M3

M4

M5

M6

M7

M8

M9

M10

0

0

1

0

1

1

1

1

0

1

图4

现在又要用到我刚才说的那个强大的公式了,请看图2,算了,为了你不至于来回拨弄鼠标滚轮,我还是把图2 粘贴过来吧


















































S1

=

M1

M3

M5

M7

M9

S2

=

M2

M3

M6

M7

M10

S3

=

M4

M5

M6

M7



S4

=

M8

M9

M10





把图4中的值,带入到图2 的公式里

S1=0⊕1⊕1⊕1⊕0       =1

S2=0⊕1⊕1⊕1⊕1       =0

S3=0⊕1⊕1⊕1           
=1

S4=1⊕0⊕1                
=0

按照S4S3S2S1排列得到的二进制数为:0101,对应的值十进制为5。

时间: 2024-12-15 01:34:57

能将0和1两个数字玩的如此传神!是个程序要都应该了解的海明码(通俗版)的相关文章

使用SHELL完成两个数字的大小比较

简要说明: 提示用户输入两个数字: 判断输入的内容是否都为数字: 数字做计算并反馈结果: 计算完毕后询问客户是否继续使用: 给用户提供随时退出的方法. [[email protected] scripts]# cat jisuan2.sh #!/bin/bash ###thank_oldboy ###2016/3/6 ###i wish you all the best. . /etc/init.d/functions ### read number. function read_number(

程序员面试100题之十:快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值(转)

能否快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值,为了简化起见,我们假设这个数组中肯定存在至少一组符合要求的解. 假如有如下的两个数组,如图所示: 5,6,1,4,7,9,8 给定Sum= 10 1,5,6,7,8,9 给定Sum= 10 分析与解法 这个题目不是很难,也很容易理解.但是要得出高效率的解法,还是需要一番思考的. 解法一 一个直接的解法就是穷举:从数组中任意取出两个数字,计算两者之和是否为给定的数字. 显然其时间复杂度为N(N-1)/2即O(N^2).这个算法很简

和为s的两个数字

牛客上要求返回乘积最小的,实际上不用麻烦去写另外一个函数,第一次找到两个数字的乘积就一定是最小的. 在调试程序时也遇到两个问题: 1.既然用到了vector容器,头文件就应该声明#include<vector> 2.vector的初始化的一种方式: int b[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};    vector<int> base(b,b+20); class Solution { public:

编程算法 - 和为s的两个数字 代码(C)

和为s的两个数字 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入一个递增排序的数组和一个数字s, 在数组中查找两个数, 使得它们的和正好是s. 假设有多对数字的和等于s, 输出随意一对就可以. 排序数组, 则能够从两端(即最大值, 最小值)開始进行查找, 当和大于时, 则降低前端, 当和小于时, 则递增尾端. 时间复杂度O(n). 代码: /* * main.cpp * * Created on: 2014.6.12 * Author

和为S的两个数字VS和为S的连续正数序列

题目:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s.如果有多对数字的和等于s,输出任意一对即可. 思路:最初我们找到数组的第一个数字和最后一个数字.首先定义两个指针,第一个指针指向数组的第一个(也就是最小的)数字,第二个指针指向数组的最后一个(也就是最大的)数字.当两个数字的和大于输入的数字时,把较大的数字往前移动:当两个数字的和小于数字时,把较小的数字往后移动:当相等时,打完收工.这样扫描的顺序是从数组的两端向数组的中间扫描. #include "stdafx.

为什么计算机只有0和1两个数字啊?

为什么计算机只有0和1两个数字啊? 当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的.计算机中的二进制则是一个非常微小的开关,用“开”来表示1,“关”来表示0. 在数字世界里没有电影.没有杂志.没有一首首的乐曲,只有一个个的数字“1”和“0”.以前人们对于数字世界中的这两个数字还不知道如何命名,直到现1946年普林斯顿大学的统计学家约翰.土吉(john turkey)把它定为进制,才有了比特(Bit)这一术语.比特是电脑当中最小的单位(0或1),1MB=1024K

经典算法学习——快速找出数组中两个数字,相加等于某特定值

这个算法题的描述如下:快速找出一个数组中的两个数字,让这两个数字之和等于一个给定的值.目前我假设数组中的都是各不相等的整数.这道题是我在一次面试中被问到的,由于各种原因,我没回答上来,十分尴尬.其实这道题十分简单,我们使用相对巧妙的方法来实现下.注意不使用两层循环的元素遍历.示例代码上传至:https://github.com/chenyufeng1991/SumTo100 . 算法描述如下: (0)首先对原数组进行排序,成为递增数组: (1)对排序后的数组头部i [0]和数组尾部j [n-1]

Python算法题----在列表中找到和为s的两个数字

列表data的值为[1, 3, 4, 5, 8, 9, 11],找出这个列表中和为13的两个数字的所有组合.这个好找,上过幼儿园大班的,估计都能找出来.4+9=13, 5+8=13.如何用python写一个函数来实现呢. 解法一: 超级大循环 最容易想到的就是遍历啊.嵌套循环,外层循环遍历全部列表,内层循环遍历当前元素位置之后的所有元素.内层循环中将两个数字相加,等于13就break.妥妥找到. def equalSum01(data=None, twosum=13):     result =

shell两个数字的运算,一共三个变量

#!/bin/bash #两个数运算的简单脚本 22 + 33 ,一共三个参数 echo $# #对获取的参数以此判断是否包含[a-zA-Z]的东西,如果包含就退出.因为数字相加不是数字就是加减乘除 for i_args in "[email protected]" do echo $i_args if [[ ${i_args} =~ [a-zA-Z]+ ]];then echo "contain illegal character" exit 1 fi done