汉明码:
汉明码是由Richard Hanming于1950年提出的,它具有一位纠错能力。
设欲检测的二进制数据为n位,为使其具有纠错能力,需增添k位检测位,组成n+k位的数据。为了能准确对错误定位以及指出数据没错,新增添的检测位数k应满足:
2k≥n+k+1
由此关系求得不同数据长度n所需检测位的位数k,如下表:
数据长度与检测位位数的关系
|
n |
k(最小) |
|
1 |
2 |
|
2~4 |
3 |
|
5~11 |
4 |
|
12~26 |
5 |
|
27~57 |
6 |
|
58~120 |
7 |
k确定后,便可由它们所承担的检测任务设定它们在编程后的数据中的位置及取值。
设n+k位编码后的数据自左至右依次编号为第1,2,3,…,n+k位,而将k位检测位记作Ci(i=1,2,4,8,…),分别安插在第1,2,4,8,…,2k-1位上。这些检测位的位置设置是为了保证它们能分别承担n+k位数据中不同数位所组成的“小组”的奇偶检测任务,使检测位和它负责检测的小组中1的个数为奇数或为偶数,具体分配如下:
C1检测的g1小组包含第1,3,5,7,9,11,…位
C2检测的g2小组包含第2,3,6,7,10,11,14,15,…位
C3检测的g3小组包含第4,5,6,7,12,13,14,15,…位
C4检测的g4小组包含第8,9,10,11,12,13,14,15,24,…位
…
这种小组的划分具有如下特点:
1)每个小组gi有一位且仅有一位为它独占,即gi小组独占第2i-1位(i=1,2,3,…)
2)每两个小组gi和gj共同占有一位是其他小组没有的,即每两个小组gi和gj共同占有第2i-1+2j-1位(i,j=1,2,3…)
3)每三个小组gi、gj和gk共同占有第2i-1+2j-1+2k-1位,是其他小组没有的
依次类推,便可确定每组所包含的各位。
以n=4, k=3为例,数据为b4b3b2b1,它们的位置安排如下:
|
二进制序号 |
1 2 3 4 5 6 7 |
|
名称 |
C1 C2 b4 C4 b3 b2 b1 |
如果按偶原则来配置汉明码,则C1应使第1,3,5,7位中“1”的个数为偶数,C2应使第2,3,6,7位中的“1”的个数为偶数,C4应使第4,5,6,7位中的“1”的个数为偶数。
令b4b3b2b1=0101,则:
C1= b4xor b3xor b1 = 0xor 1 xor 1 = 0
C2= b4xor b2xor b1 = 0xor 0 xor 1 = 1
C4= b3xor b2xor b1 = 1xor 0 xor 1 = 0
故对数据0101进行汉明码编码后为C1C2b4C4b3b2b1,即0100101。
汉明码的纠错过程实际上是对汉明码编码后的数据形成新的检测位Pi(i=1,2,4,8,…),根据Pi的状态,便可直接指出错误的位置。同样的,以n=4, k=3为例。
P1= C1xor b4xor b3xor b1
P2= C2xor b4xor b2xor b1
P4= C4xor b3xor b2xor b1
若正确汉明码为0100101,出错后的数据为0100111,则计算得到P4P2P1=110,这表示第6位出错了,于是我们将第6位由“1”改成“0”,便得到纠错后的正确数据。
交织技术:
对于每一个数据帧,汉明码可以纠正一位随机错误,但对于突发性的集中错误无能为力。为了解决这个问题,我们使用交织技术将突发性的集中错误转换成随机错误来解决。
交织是把经过汉明码编码的数据矩阵进行转置操作后,对数据进行重新排列,不添加冗余比特。
使用汉明码编码之后的秘密信息矩阵为:
|
C11C12b14C14b13b12b11 C21C22b24C24b23b22b21 |
|
C31C32b34C34b33b32b31 |
|
C41C42b44C44b43b42b41 |
进行交织编码之后的秘密信息矩阵为:
|
C11 C12 b14 C14 b13 b12 b11 |
C21 C22 b24 C24 b23 b22 b21 |
C31 C32 b34 C34 b33 b32 b31 |
C41 C42 b44 C44 b43 b42 b41 |
当发生集中错误时,如b14b24b34b44这4个连续的比特位均出错时,由于进行了交织编码,这4个连续的比特位实际上分别属于4个不同的汉明码,于是我们可以利用汉明码的纠错能力将这次的集中错误修复。
算法整体流程:
原文->汉明编码->交织编码->处理后的信息
传输
收到的信息->反交织编码->汉明码译码并纠错->原文
代码如下:
原文放在1.txt中.
#include <stdio.h>
#include <stdlib.h>
//(7,4)hamming code encode
char hammingEncode(char ori)
{
char b4,b3,b2,b1;
b4=(ori&8)>>3;
b3=(ori&4)>>2;
b2=(ori&2)>>1;
b1=ori&1;
char c1,c2,c4;
c1=b4^b3^b1;
c2=b4^b2^b1;
c4=b3^b2^b1;
//最高位不用
char output=0;
output+=c1<<6;
output+=c2<<5;
output+=b4<<4;
output+=c4<<3;
output+=b3<<2;
output+=b2<<1;
output+=b1;
return output;
// fwrite(&output,1,1,fp);
}
//(7,4)hamming code decode
char hammingDecode(char enc,char flag)
{
char c1,c2,b4,c4,b3,b2,b1;
char output=0;
c1=(enc&64)>>6;
c2=(enc&32)>>5;
b4=(enc&16)>>4;
c4=(enc&8)>>3;
b3=(enc&4)>>2;
b2=(enc&2)>>1;
b1=enc&1;
char p1,p2,p4;
p1=c1^b4^b3^b1;
p2=c2^b4^b2^b1;
p4=c4^b3^b2^b1;
int errorIndex=p4*4+p2*2+p1;
if(errorIndex)printf("error happen !\n");
switch(errorIndex)
{
case 3:
b4=(b4>0?0:1);
break;
case 5:
b3=(b3>0?0:1);
break;
case 6:
b2=(b2>0?0:1);
break;
case 7:
b1=(b1>0?0:1);
break;
default:
printf("pass!\n");
}
if(flag==0)//高4位
{
output+=b4<<7;
output+=b3<<6;
output+=b2<<5;
output+=b1<<4;
}
else//低4位
{
output+=b4<<3;
output+=b3<<2;
output+=b2<<1;
output+=b1;
}
return output;
}
//交织
void Interweave(char *buf,int len)
{
int i,j;
char *result=malloc(len);
int bitIndex=7;
unsigned char ch=0;
int resultIndex=0;
//先取最高位,依次收集
for(i=7; i>=0; i--)
{
for(j=0; j<len; j++)
{
ch+=((buf[j]>>i)&1)<<bitIndex;
bitIndex--;
if(bitIndex<0)
{
result[resultIndex++]=ch;
ch=0;
bitIndex=7;
}
}
}
for(i=0; i<len; i++)
{
buf[i]=result[i];
}
free(result);
}
//反交织
void RInterweave(char *buf,int len)
{
int i,j;
char *result=calloc(len,sizeof(char));
int curIndex=0;
int bitIndex=7;
for(i=0; i<len; i++)
{
for(j=7; j>=0; j--)
{
result[curIndex++]+=((buf[i]>>j)&1)<<bitIndex;
if(curIndex==len)
{
bitIndex--;
curIndex=0;
}
}
}
for(i=0; i<len; i++)
{
buf[i]=result[i];
}
free(result);
}
//加密函数
void encode()
{
FILE *fs,*fp;
char ch;
//加密
fs=fopen("1.txt","r");
fp=fopen("2.txt","w");
fseek(fs,0L,SEEK_END);
int fileLen=ftell(fs);
char *buf=malloc(fileLen*2);
fseek(fs,0L,SEEK_SET);
int curIndex=0;
while(fread(&ch,1,1,fs))
{
buf[curIndex++]=hammingEncode((ch&240)>>4);
buf[curIndex++]=hammingEncode(ch&15);
}
fclose(fs);
//交织编码
Interweave(buf,curIndex);
fwrite(buf,1,curIndex,fp);
fclose(fp);
free(buf);
}
void decode()
{
FILE *fs,*fp;
int i;
//解密
fs=fopen("2.txt","r");
fp=fopen("3.txt","w");
fseek(fs,0L,SEEK_END);
int fileLen=ftell(fs);
char *buf=malloc(fileLen);
fseek(fs,0L,SEEK_SET);
fread(buf,1,fileLen,fs);
fclose(fs);
//反交织编码
RInterweave(buf,fileLen);
char flag=0;
char output=0;
for(i=0; i<fileLen; i++)
{
output+=hammingDecode(buf[i],flag);
if(!flag)flag=1;
else
{
fwrite(&output,1,1,fp);
output=0;
flag=0;
}
}
fclose(fp);
free(buf);
}
int main()
{
encode();
decode();
return 0;
}
本文介绍了汉明码的概念,包括其纠错原理和编码过程,并通过实例展示了如何对数据进行汉明编码和纠错。同时,文章探讨了汉明码在处理突发性集中错误时的局限性,提出通过交织技术将集中错误分散为随机错误,提高纠错能力。最后,概述了整体的算法流程,从原文到传输再到接收端的解码纠错过程。

1万+

被折叠的 条评论
为什么被折叠?



