汉明码实现原理


汉明码(Hamming Code)是广泛用于内存和磁盘纠错的编码。汉明码不仅可以用来检测转移数据时发生的错误,还可以用来修正错误。(要注意的是,汉明码只能发现和修正一位错误,对于两位或者两位以上的错误无法正确和发现)。

 
汉明码的实现原则是在原来的数据的插入k位数据作为校验位,把原来的N为数据变为m(m = n +k)位编码。其中编码时要满足以下原则:
2^k - 1 >= m 其中(m = n + k)
这就是Hamming不等式,汉明码规定,我们所得到的m位编码的2^k ( k>=0 && 2^k < m)位上插入特殊的校验码,其余位把源码按顺序放置。
 
汉明码的编码规则如下:
  • 在新的编码的2^(k - 1)( k >= 0)位上填入0(即校验位)
  • 把新的编码的其余位把源码按原顺序填入
  • 校验位的编码方式为:第k位校验码从则从新的编码的第2^(k - 1)位开始,每计算2^(k - 1)位的异或,跳2^(k - 1)位,再计算下一组2^(k - 1)位的异或,填入2^(k - 1)位,比如:
    第1位校验码位于新的编码的第1位(2 ^(1-1) == 1)(汉明码从1位开始),计算1,3,5,7,9,11,13,15,...位的异或,填入新的编码的第1位。
    第2位校验码位于新的编码的第2位(2 ^(2-1) == 2),计算2,3,6,7,10,11,14,15,...位的异或,填入新的编码的第2位。
    第3位校验码位于新的编码的第4位(2 ^(3-1) == 4),计算4,5,6,7,12,13,14,15,20,21,22,23,...位的异或,填入新的编码的第4位。
    第4位校验码位于新的编码的第8位(2 ^(4-1) == 8),计算8-15,24-31,40-47,...位的异或,填入新的编码的第8位。
    第5位校验码位于新的编码的第16位(2 ^(5-1) == 16),计算16-31,48-63,80-95,...位的异或,填入新的编码的第16位。
 
 
汉明码编码实例

以10101编码为例,创建一个汉明码编码的空间,并且把源码填入编码的对应位中中,_ _ 1 _ 0 10 _ 1,并留出校验码位(校验位先设为0)。(因为2^4 - 1>= 5+4 && 2^3 - 1 < 5+ 3所以需要4位校验码)
  • 计算校验码的第1位(1,3,5,7,9进行异或): 结果为0,所以汉明码第2^0位为0,结果为0 _ 1 _ 0 10 _ 1
  • 计算校验码的第2位(2,3,6,7进行异或): 结果为0,所以汉明码第2^1位为0,结果为001 _ 0 10 _ 1
  • 计算校验码的第3位(4,5,6,7进行异或): 结果为1,所以汉明码第2^2位为0,结果为0011 0 10 _ 1
  • 计算校验码的第4位(8, 9进行异或): 结果为0,所以汉明码第2^3位为1,结果为0011 0101 1
  • 所以最终编码为001101011.
 
 
汉明码校验错误实例

我们以上面的编码为例,假设我们现在收到的编码为001101001,我们可以发现汉明码的第8位与原来的汉明码001101011不同,那我们怎么找出这个第8位的错误编码呢?
 
算法很简单,我们只要在算汉明码校验位的算法的上再算一遍,就得到了汉明码的校验方法,比如计算001101001对应的2^k位。

1,3,5,7,9进行异或,得到0

2,3,6,7进行异或,得到0

4,5,6,7进行异或,得到0

8,9进行异或,得到1

我们把上述结果反着排列,得到1000,即十进制的8,根据汉明码的校验规则,编码出错的地方即在第8位,我们把第8位的0换成1,即可得原来的编码001101011。
 
上述的例子是出现在2^k的校验位上的,如果出现在非2^k位上,得到的结果也是一样的,比如:
假设收到的编码为001100011,即第6位出了错误,我们根据规则

1,3,5,7,9进行异或,得到0

2,3,6,7进行异或,得到1

4,5,6,7进行异或,得到1

8,9进行异或,得到0

我们把上述结果反着排列,得到0110,即十进制的6,根据汉明码的校验规则,编码出错的地方即在第6位,我们把第6位的0换成1,即可得原来的编码001101011。
 
汉明码的编码和校验的C++实现

通过原理,我们可以很简单地实现汉明码的编码和校验代码
编码:
auto cal(size_t sz)->decltype(auto)
{
decltype(sz) k = ;
decltype(sz) cur = ;
while (cur - < sz + k )
{
cur <<= ;
k++;
}
return k;
}
bool encode(const string &s, string &d)
{
d.clear();
auto k = cal(s.size());
d.resize(s.size() + k);
for (decltype(d.size()) i = , j = , p = ; i!= d.size();i++)
{
if ((i + ) == pow(,p) && p < k)
{
d[i] = '';
p++;
}
else if (s[j] == '' || s[j] == '')
d[i] = s[j++];
else
return false;
}
for (auto i = ; i != k;i++)
{
int count = ,index = << i;
for (auto j = index - ; j < d.size() ;j += index)
for (auto k = ; k!= index && j < d.size(); k++, j++)
count ^= d[j] - '';
d[index - ] = '' + count;
}
return true;
}
 
解码与校验:
auto antiCal(size_t sz)->decltype(auto)
{
decltype(sz) k = ;
decltype(sz) cur = ;
while (cur < sz)
{
cur <<= ;
k++;
}
return k;
} auto decode(string &s, string &d)->decltype(auto)
{
s.clear();
auto k = antiCal(d.size());
s.resize(d.size() - k); decltype(d.size()) sum = ;
for (decltype(k) p = ;p != k;p++)
{
int pAnti = ;
decltype(k) index = << p;
for (decltype(d.size()) i = index - ;i < d.size(); i+=index)
{
for (auto j = ; j < index && i < d.size(); i++, j++)
pAnti ^= d[i] - '';
}
sum += pAnti << p;
}
if (sum != )
d[sum - ] = (- (int)(d[sum - ] - '')) + ''; for (decltype(d.size()) i = , p = ,j = ; i != d.size(); i++)
{
if ((i + ) == ( << p) && p < k)
p++;
else
s[j++] = d[i];
} return sum;
}
测试样例:
int main()
{
string source, dest;
while (cin >> source)
{
if (encode(source,dest))
{
cout << "Source: " <<source << endl;
cout << "Dest: " << dest << endl;
}
size_t index;
cout << "----input error index : ";
cin >> index;
auto k = dest.size();
if (index != && index <= dest.size())
dest[index - ] = ( - (int)(dest[index - ] - '')) + '';
cout << "Code " << dest <<endl;
auto ret = decode(source,dest);
if (ret == )
{
cout << "Source: " <<source << endl;
cout << "Dest: " <<dest << endl;
}
else
{
cout << "Error index "<< ret << endl;
cout << "Corret source: " <<source << endl;
cout << "Corret dest: " <<dest << endl;
}
cout << endl;
}
return ;
} Source:
Dest:
----input error index :
Code
Error index
Corret source:
Corret dest: 001101011 Source:
Dest:
----input error index :
Code
Error index
Corret source:
Corret dest: 1111001101010100101010101111110101101 Source:
Dest:
----input error index :
Code
Source:
Dest:
 
 
 
 

汉明码(Hamming Code)原理及实现的更多相关文章

  1. 汉明码(hamming code)

    hamming code用于磁盘RAID 2中, 关于汉明码的讲解可以看这篇博文,介绍的很详细.最重要是最后的结论: 汉明码属于分组奇偶校验,P4P2P1=000,说明接收方生成的校验位和收到的校验位 ...

  2. URAL 1792. Hamming Code (枚举)

    1792. Hamming Code Time limit: 1.0 second Memory limit: 64 MB Let us consider four disks intersectin ...

  3. 汉明码、海明校验码(Hamming Code)

    目录 基础知识 汉明码/海明校验码 计算 基础知识 码距:又叫海明距离,是在信息编码中,两个编码之间对应位上编码不同的位数.例如编码100110和010101,第1.2.5.6位都不相同,所以这两个编 ...

  4. Hamming code

    Also known as (7,4) code,7 trainsmitted bits for 4 source code. TRANSMIT The transmitted procedure c ...

  5. Google Interview University - 坚持完成这套学习手册,你就可以去 Google 面试了

    作者:Glowin链接:https://zhuanlan.zhihu.com/p/22881223来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 原文地址:Google ...

  6. NAND FLASH特性说明

    1.NAND FLASH 的特殊性. 1)存在坏块.由于NAND生产工艺的原因,出厂芯片中会随机出现坏块.坏块在出厂时已经被初始化,并在特殊区域中标记为不可用,在使用过程中如果出现坏块,也需要进行标记 ...

  7. 存储系列之 RAID技术原理简介

    引言:RAID技术是现代大规模存储的基础,“基础(技术)是拿来革命的”.我查raid相关资料时,查布尔运算,竟然一路查到“香农原理”,这不是有个视频中HW的任总提到的吗,多基础的东西,任总却毫不含糊, ...

  8. 痞子衡嵌入式:走进二维码(QR Code)的世界(1)- 引言

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是走进二维码(QR Code)的世界专题的引言. 如今二维码可以说是深入走进大家的生活了,推送名片.扫码支付都离不开它,大家几乎每天都会和 ...

  9. 痞子衡嵌入式:走进二维码(QR Code)的世界(2)- 初体验(PyQt5.11+MyQR2.3+ZXing+OpenCV4.2.0)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是走进二维码(QR Code)的世界专题之初体验. 接上篇 <走进二维码(QR Code)的世界(1)- 引言> 继续更文,在 ...

随机推荐

  1. ZOJ2898【折半搜索】

    题意: 给出一系列值和对应的陷阱,对于陷阱如果存在两个就抵消,求价值最大. 思路: 折半枚举,利用异或 #include <bits/stdc++.h> using namespace s ...

  2. 51nod1153(dfs/单调队列)

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1153 题意:中文题诶- 思路:一个比较简单的方法是dfs隐式 ...

  3. uoj#213. 【UNR #1】争夺圣杯(单调栈)

    传送门 我们枚举每一个元素,用单调栈做两遍计算出它左边第一个大于它的位置\(l[i]\)和右边第一个大于它的位置\(r[i]\),那么一个区间以它为最大值就意味着这个区间的左端点在\([l[i]+1, ...

  4. IT兄弟连 Java语法教程 Java语言的跨平台特性

    什么是平台 Java是可以跨平台的编程语言,那么首先我们需要知道什么是平台,通常我们把CPU与操作系统的整体称为平台. CPU大家都知道,是计算机的大脑,它既负责思维运算,又负责计算机中各种零部件的命 ...

  5. js 获取两个日期相差的天数--自定义方法

    //获取两个日期的相差天数 datedifference=function(sDate1, sDate2) { var dateSpan, tempDate, iDays; sDate1 = Date ...

  6. Python面向对象之魔法方法/双下方法

    1.__new__ and __init__ 这两个方法都是在实例化的时候执行,__new__ 在 __init__ 之前执行,并且 如果实例化的时候封装属性,__new__也是必须要传的,而且__n ...

  7. Django模板语言,标签整理

    Django模板语言 标签 内置标签引用 1. autoescape 控制自动转义是否可用. 这种标签带有任何 on 或 off 作为参数的话,他将决定转义块内效果. 该标签会以一个endautoes ...

  8. python大战机器学习——支持向量机

    支持向量机(Support Vector Machine,SVM)的基本模型是定义在特征空间上间隔最大的线性分类器.它是一种二类分类模型,当采用了核技巧之后,支持向量机可以用于非线性分类. 1)线性可 ...

  9. NET full stack framework

    NFX UNISTACK 介绍 学习.NET Core和ASP.NET Core,偶然搜索到NFX UNISTACK,现翻译一下Readme,工程/原文:https://github.com/aumc ...

  10. NET Core应用中实现与第三方IoC/DI框架的整合?

    NET Core应用中实现与第三方IoC/DI框架的整合? 我们知道整个ASP.NET Core建立在以ServiceCollection/ServiceProvider为核心的DI框架上,它甚至提供 ...