汉明编码 Hamming

介绍

由Richard Hamming于1950年提出、还被广泛采用的一种很有效的校验方法,是只要增加少数几个校验位,就能检测出二位同时出错、亦能检测出一位出错并能自动恢复该出错位的正确值的有效手段,后者被称为自动纠错。它的实现原理,是在k个数据位之外加上r个校验位,从而形成一个k+r位的新的码字,使新的码字的码距比较均匀地拉大。把数据的每一个二进制位分配在几个不同的偶校验位的组合中,当某一位出错后,就会引起相关的几个校验位的值发生变化,这不但可以发现出错,还能指出是哪一位出错,为进一步自动纠错提供了依据。

代码:

#include<bits/stdc++.h> 
using namespace std; 

class Ham {
	public:	
	
	void print_16(int sum)//输出对应的十六进制值 
	{
		if(sum<9) cout<<sum;
		else if(sum == 10) cout<<"A";
		else if(sum == 11) cout<<"B";
		else if(sum == 12) cout<<"C";
		else if(sum == 13) cout<<"D";
		else if(sum == 14) cout<<"E";
		else if(sum == 15) cout<<"F";
	}
	void print_result_16(int code_result[],int len) //按十六进制转换 
	{ 
		int remain = len % 4 ;
		int sum = 0;
		int power = 0;
		for(int i = remain   ; i >  0 ; i-- ) 
		{
			sum += code_result[i]*pow(2,power++);
		} 
	 	print_16(sum);
		for(int i=0;i<len/4;i++)
		{
			sum = 0; power = 0;
			for(int j = remain+i*4+4 ;j > remain+i*4;j--)
			{
				sum += code_result[j]*pow(2,power++);;
			}
			print_16(sum);
		}
	}
	bool  judge_if_1(int num,int pos)//判断某个数的某一位是否为 1 
	{
		const int Size = 32;
		char str[Size];
		bitset<Size> bs(num);
		strcpy(str, bs.to_string().c_str()); 
		if(str[32-pos] == '1') return true; //如果是1,返回为真 
		return false;
	}
	
	void code()
	{
		char s[100]; 
		cout<<"输入要转化为CRC的二进制串:"<<endl; 
		cin>>s;  
		int N = strlen(s);  //待编码的串 
		int re[100] ;//保存结果
		int count = 0;   
		for(int i=1,j=0 ;j < N; i++)
		{
			if( i & (i-1) ) //如果不是2的次幂,则将其保存在结果数组中
			{
				re [i] = (int)s[j]-48; j++;
			} 
			else  
				re [i] = 0; 
			count++;//统计生成编码的长度 
  		} 
		double base = 2.0;
		for(double i = 0 ; i < count-N ; i++)
		{
			int ans = 0;
			for(int j = 1; j <= count ; j++)
			{
				if( judge_if_1(j,i+1) == true )
				{
					ans = ans ^ re[j]; 
				}
			}
			int k = pow(base,i);
//			cout<<k<<" "<<ans<<endl;
 			re[k] = ans;
		}  
 		//输出编码后的结果
 		cout<<"二进制Hamming编码:";
		for(int i=1;i<=count;i++)
		{
			cout<<re[i];
		} 
		cout<<endl;
		cout<<"十六进制Hamming编码:";
		print_result_16(re,count) ;
		cout<<endl;
	} 
	void check_code()
	{
		char s[100]; 
		cout<<"输入要检验Hamming编码的二进制串:"<<endl; 
		cin>>s;  
		int N = strlen(s);  //待编码的串 
		int re[100] ;//保存结果 
		for(int i = 0 ;i < N; i++)
		{ 
			re [i+1] = (int)s[i]-48;   
  		}  
  		int number_2_pow = 0;
		for(double i = 0 ; ; i++)
		{
			if(pow(2.0,i) >= N) {
				number_2_pow = i;break;
			}
		} 
		int check[100], cnt = 0;
		for(double i = 0 ; i < number_2_pow ; i++)
		{
			int ans = 0;
			for(int j = 1; j <= N ; j++)
			{
				if( judge_if_1(j,i+1) == true )
				{
					ans = ans ^ re[j]; 
				}
			}
			check[cnt++] = ans;
		}   
		cout<<"校验结果:";
		for(int i=cnt-1;i>=0;i--)
		{
			cout<<check[i];
		} 
		cout<<endl; 
		int sum = 0, power = 0;
		for(int i = 0 ; i < cnt ; i++ ) 
		{
			sum += check[i]*pow(2,power++);
		} 
		if(sum == 0) cout<<"Hamming编码正确"<<endl;
		else{
			cout<<"Hammming编码出现错误"<<endl; 
			cout<<"正确Hamming编码为:";  
			for(int i = 0 ;i < N; i++)
			{ 
				if(i == sum-1) {
					if(s[i]=='1') cout<<0;
					else cout<<1;
				} 
				else cout<<s[i];
	  		}  	
	  		cout<<endl;
		}
	}
};
 
int main()
{
	Ham ham; //创建crc类 
	cout<<"开始程序"<<endl;
	while(true)
	{
		cout<<"****************************************************************"<<endl; 
		cout<<"生成Hamming编码输入0,  检验Hamming编码输入1,  退出程序输入2:"<<endl;
		int choose ;
		cin>>choose;
		switch(choose)
	    {
	        case 0: ham.code(); break;//生成发送的Hamming编码
	        case 1: ham.check_code ();break;//检验Hamming编码  
	        case 2: return 0;
	    } 
	} 
	return 0;                   
}
/*
测试样例: 
开始程序
****************************************************************
生成CRC编码输入0,  检验CRC编码输入1,  退出程序输入2:
0
输入要转化为CRC的二进制串:
1010001101
CRC编码二进制: 101000110101110
CRC编码十六进制: 51AE
****************************************************************
生成CRC编码输入0,  检验CRC编码输入1,  退出程序输入2:
1
输入要验证的二进制串:
101000110101110
其余数为:00000
通过CRC验证
****************************************************************
生成CRC编码输入0,  检验CRC编码输入1,  退出程序输入2:
1
输入要验证的二进制串:
101000110101111
其余数为:10101
CRC编码出现错误
****************************************************************
生成CRC编码输入0,  检验CRC编码输入1,  退出程序输入2:
2
*/ 

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值