二进制转格雷码c语言编程,格雷码简介及格雷码与二进制的转换程序
格雷码简介及格雷码与二进制的转换程序
格雷码简介
格雷码(英文:Gray Code, Grey Code,又称作葛莱码,二进制循环码)是1880年由法国工程师Jean-Maurice-Emlle
Baudot发明的一种编码[1] ,因Frank Gray于1953年申请专利“Pulse Code
Communication”得名。当初是为了机械应用,后来在电报上取得了巨大发展[2],现在则常用于模拟-数字转换[3]和转角-数字转换中[4] 。
典型格雷码是一种具有反射特性和循环特性的单步自补码,它的循环、单步特性消除了随机取数时出现重大误差的可能,它的反射、自补特性使得求反非常方便[5] 。
格雷码属于可靠性编码,是一种错误最小化的编码,因为它大大地减少了由一个状态到下一个状态时电路中的混淆。由于这种编码相邻的两个码组之间只有一位不同,因而在用于模-数转换中,当模拟量发生微小变化而可能引起数字量发生变化时,格雷码仅改变一位,这样与其它码同时改变两位或多位的情况相比更为可靠,即可减少出错的可能性.这就允许代码电路能以较少的错误在较高的速度下工作。
格雷码在现代科学上获得了广泛的应用,人们还发现智力玩具九连环的状态变化符合格雷码的编码规律,汉诺塔的解法也与格雷码有关。
除了已知的特点,格雷码还有一些鲜为人知的性质。多数数字电子技术和计算机技术的文献认为格雷码是无权码,只有J.F.A.
Thompson认为可以从格雷码直接转换成十进制数[6]。如果将格雷码的“权”及格雷码的奇偶性等性质在数学上给予证明,将有助于格雷码研究与应用的发展,有助于自动化技术的发展,还可有助于计算机科学的发展。
/* 格雷码与二进制的转换程序
* 本程序采用递推的方法进行推导,可以转换0~2147483647之间的数(1~31位)
* 推导方式如下(以三位格雷码为例):
* 序号 格雷码 格雷码实值 二进制码 二进制实值
* 0 000 0 000 0
* 1 001 1 001 1
* 2 011 3 010 2
* 3 010 2 011 3
* 4 110 6 100 4
* 5 111 7 101 5
* 6 101 5 110 6
* 7 100 4 111 7
* 由上面的数据可看出.如果,按照序号01327645的方式遍历格雷码.其编
* 码实值是按自然数顺序排列.反之,如果按此顺序遍历其二进制实值.则会发
* 现遍历过的数据的个数减一即为二进制码所对应格雷码的实值.再观察序号
* 顺序,我们会发现: 如果把二进制码分半,前半部分从前向后遍历,后半部分
* 从后向前遍历.如果分半部分可再分,则再将其分半.并按照前半部分从前向
* 后遍历(分解),后半部分从后向前遍历的方式遍历(分解).直到不可分.即可
* 实现按序号所描述顺序遍历二进制码.如果,按此顺序遍历二进制码,我们可
* 以很方便地在序列中找到所要的二进制码与其对应的格雷码.本思想可以很
* 方便地用递归实现.这样就实现了二进制到格雷码的转换.同样,格雷码到二
* 进制的转换,也可以用相同的方法推出.为了加快运算,我们跳过不必要的遍
* 历将递归改为递推.这样就实现了格雷码与二进制之间的快速转换.
* 此算法的时间复杂度约为O(n),n为要转换数据的BIT数.
* *****************************************************************
* 补充说明:
* 其它的转换方法还有
* 1、查表法(建立一个二进制与格雷码的对应表)
* 2、公式法(根据卡诺图建立一个二进制到格雷码的每一位的公式)
*/
//#define test
#i nclude
#ifdef test
#i nclude
#endif
/**
* 二进制转换成格雷码
* @param lStart lValue所在区间下界
* @param lEnd lValue所在区间上界
* @param lValue 要转换的二进制数的实值
* @return 返回格雷码对应的二进制数的实值
* @see g2b() g2b 格雷码转换二进制
* @see BtoG() BtoG 二进制转换格雷码
* @see GtoB() BtoG 格雷码转换二进制
* @author 黄毅
* @useage a=b2g(0,15,4); //取得4所对应格雷码的二进制值 结果a等于6
* @memo lValue的值必须在区间[lStart,lEnd]里,否则无法求得所求结果.相应地,如果区间越小,求得结
* 果所用的时间就越少.而且lStart,lEnd的值必须为2的N次方减1. 通常lStart为0.为了方便求得
* 其值,建议使用BtoG()函数来进行操作.不过这样会使计算时间加长到原来的120%~180%.
*/
unsigned long b2g(unsigned long lStart,unsigned long lEnd,unsigned
long lValue)
{
unsigned long Start=lStart,End=lEnd,Temp=0,Counter=0;
bool Type=true;
while(Start
{
Temp=(End+Start-1)>>1;
if (lValue<=Temp)
{
if(!Type)
Counter+=((End-Start+1)>>1);
End=Temp;
Type=true;
}
else
{
if(Type)
Counter+=((End-Start+1)>>1);
Start=++Temp;
Type=false;
}
}
return Counter;
}
/**
* 格雷码转换成二进制
* @param lStart lValue对应二进制数所在区间下界
* @param lEnd lValue对应二进制数所在区间上界
* @param lValue 要转换的格雷码的实值
* @return 返回二进制数对应的格雷码的实值
* @see b2g() b2g 二进制转换格雷码
* @see BtoG() BtoG 二进制转换格雷码
* @see GtoB() BtoG 格雷码转换二进制
* @author 黄毅
* @useage a=b2g(0,15,6); //取得6所对应二进制值的格雷码 结果a等于4
* @memo lValue对应二进制数的值必须在区间[lStart,lEnd]里,否则无法求得所求结果.相应地,如果区
* 间越小,求得结果所用的时间就越少.而且lStart,lEnd的值必须为2的N次方减1. 通常lStart为0.
* 为了方便求得其值,建议使用GtoB()函数来进行操作.但会使计算时间加长到原来的105%~140%.
*/
unsigned long g2b(unsigned long lStart,unsigned long lEnd,unsigned
long lValue)
{
unsigned long Start=lStart,End=lEnd,Counter=0,Temp=0;
bool Type=true;
while(Start
{
Temp=Counter+((End-Start+1)>>1);
if(Type^(lValue
{
if(Type) Counter=Temp;
Start=(Start+End+1)>>1;
Type=false;
}
else
{
if(!Type) Counter=Temp;
End=(Start+End-1)>>1;
Type=true;
}
}
return Start;
}
//b2g外壳程序,用来算lStart,lEnd;
long BtoG(unsigned long lValue)
{
register unsigned long lV=lValue,lMax=1;
while (lV>0)
{
lV>>=1;
lMax<<=1;
}
if (lMax==0) return -1;
return b2g(0,--lMax,lValue);
}
//g2b外壳程序
long GtoB(unsigned long lValue)
{
register unsigned long lV=lValue,lMax=1;
while (lV>0)
{
lV>>=1;
lMax<<=1;
}
if (lMax==0) return -1;
return g2b(0,--lMax,lValue);
}
main()
{
long input=0;
#ifdef test
//程序测试部分
clock_t cStart,cEnd;
unsigned long dTime;
cStart=clock();
for (input=0;input<9999999;input++)
BtoG(32768);
cEnd=clock();
dTime=(cEnd-cStart);
printf("BtoG: %ld / %ld\n",dTime,CLOCKS_PER_SEC);
//------------------------------------------------------
cStart=clock();
for (input=0;input<9999999;input++)
b2g(0,65535,32768);
cEnd=clock();
dTime=(cEnd-cStart);
printf("b2g: %ld / %ld\n",dTime,CLOCKS_PER_SEC);
//------------------------------------------------------
cStart=clock();
for (input=0;input<9999999;input++)
GtoB(32768);
cEnd=clock();
dTime=(cEnd-cStart);
printf("GtoB: %ld / %ld\n",dTime,CLOCKS_PER_SEC);
//------------------------------------------------------
cStart=clock();
for (input=0;input<9999999;input++)
g2b(0,65535,32768);
cEnd=clock();
dTime=(cEnd-cStart);
printf("g2b: %ld / %ld\n",dTime,CLOCKS_PER_SEC);
#else
//程序演试部分
printf("Input(HEX):");
scanf("%x",&input);
while (input!=-1)
{
printf("------BtoG------\nBinary:%08Xh\nGray
:%08Xh\n------GtoB------\nGray
:%08Xh\nBinary:%08Xh\n----------------\n",input,BtoG(input),input,GtoB(input));
printf("Input(HEX):");
scanf("%x",&input);
}
#endif
======================================================================================二进制格雷码与自然二进制码的互换(2)
三、二进制格雷码与自然二进制码互换的实现方法
1、自然二进制码转换成二进制格雷码
A)、软件实现法(参见示例工程中的 Binary to Gray)
根据自然二进制转换成格雷码的法则,可以得到以下的代码:
static unsigned int DecimaltoGray(unsigned int x)
{
return x^(x>>1);
}
//以上代码实现了unsigned int型数据到格雷码的转换,最高可转换32位自然二进制码,超出32位将溢出。
static int DecimaltoGray( int x)
{
return x^(x>>1);
}
//以上代码实现了 int型数据到格雷码的转换,最高可转换31位自然二进制码,超出31位将溢出。
上述代码即可用于VC控制程序中,也可以用于单片机控制程序中。在单片机程序设计时,若采用汇编语言编程,可以按相同的原理设计程序;若采用C语言编程,则可以直接利用上述代码,但建议用unsigned int函数。
2、二进制格雷码转换成自然二进制码
A)、软件实现法(参见示例工程中的 Gray to Binary )
根据二进制格雷码转换成自然二进制码的法则,可以得到以下的三种代码方式:
static unsigned int GraytoDecimal(unsigned int x)
{
unsigned int y = x;
while(x>>=1)
y ^= x;
return y;
}
static unsigned int GraytoDecimal(unsigned int x)
{
x^=x>>16;
x^=x>>8;
x^=x>>4;
x^=X>>2;
x^=x^1;
return x;
}
static unsigned int GraytoDecimal(unsigned int x)
{
int i;
for(i=0;(1<
{
x^=x>>(1<
}
return x;
}
//以上代码实现了unsigned int型数据到自然二进制码的转换,最高可转换32位格雷码,超出32位将溢出。将数据类型改为int型即可实现31位格雷码转换。
上述代码即可用于VC控制程序中,也可以用于单片机控制程序中。在单片机程序设计时,若采用汇编语言编程,可以按相同的原理设计程序;若采用C语言编程,则可以直接利用上述代码,但建议用unsigned int函数。
二进制转格雷码c语言编程,格雷码简介及格雷码与二进制的转换程序相关推荐
- 51单片机二进制转bcd码c语言,16位二进制数转换成BCD码的的快速算法-51单片机...
在做而论道上篇博文中,回答了一个16位二进制数转换成BCD码的问题,给出了一个网上广泛流传的经典转换程序. . 说它经典,不仅是因为它已经流传已久,重要的是它的编程思路十分清晰,十分易于延伸推广.做而 ...
- mysql创建表里主码和外码_SQL语言创建表时候怎么定义主码和外码
展开全部 SQL语言62616964757a686964616fe58685e5aeb931333433623064创建表时候用Primary Key(属性名)定义主码,用Foreign Key(属性 ...
- c语言 补码转原码,C语言编程之二进制原码、反码和补码
概述 在计算机内,有符号数有3种表示法:原码.反码和补码. 在计算机中,数据是以补码的形式存储的,所以补码在c语言的教学中有比较重要的地位,而讲解补码必须涉及到原码.反码. 详细释义 所谓原码就是二进 ...
- c语言能让制表符空9个字符码,C语言编程规范 – 嗨!大佟!
1. 背景 无论如何,标准是团队开发的保证之一,而且标准欢迎争吵和变化.我们使代码易于管理的方法之一是增强代码一致性,让别人可以读懂你的代码是很重要的,保持统一编程风格意味着可以轻松根据"模 ...
- c语言数独程序源码,c语言编程:优化回溯解数独程序
上次在博客上发了一篇<C语言:回溯解数独程序>.实在很粗糙,效率相当差.正如在群里一位朋友说的: 你能不能别像傻瓜式一样从左到右从上到下这样搜索呢?如果你这样,我出第一行是空的数独题,那你 ...
- c语言数组与指针编程源码,C语言编程(练习9:数组与指针)
题目:有 5 个字符串,首先将它们按照字符串中的字符个数由小到大排列,再分别取出每个字符串的第三个字母合并成一个新的字符串输出(若少于三个字符的输出空格).要求:利用字符串指针和指针数组实现. 代码实 ...
- c#语言经典程序100例,C#入门必看的实例程序100个 - 源码下载|Windows编程|其他小程序|源代码 - 源码中国...
C#入门必看的实例程序100个\实例01\01.bmp C#入门必看的实例程序100个\实例01\csc编译器路径.txt C#入门必看的实例程序100个\实例01\hello.cs C#入门必看的实 ...
- c语言门禁系统源代码,D01_门禁管理系统 - 源码下载|Windows编程|其他小程序|源代码 - 源码中国...
文件名大小更新时间 D01_门禁管理系统\.vs\D01_门禁管理系统\v15\.suo204802019-05-28 D01_门禁管理系统\.vs\slnx.sqlite2375682019-05- ...
- c语言字符类型强制换成内码,C语言实现不同汉字系统的内码转换方法
摹14●摹 1囊 l9髓 丰 3̂ 齐 弃 靖尔 大 学学 报 J伽rn|l 0fQiq 嘶 劬 q 言实现不 字 |I∈峰 张宏烈 周长支 一 1 / (齐弃暗拳太掌工鼍qb,一r /1 -i l ...
- C语言—编程机制(简介)_成仙不问道
生成程序的具体过程因计算机环境而异. C编程机制:通过程序把源代码文件转换为可执行文件(其中包含可直接运行的机器语言代码).典型C实现通过编译和链接两个步骤来完成这一过程.编译器把源代码转换成中间代码 ...
最新文章
- babel css3新特性_前端总结(后续不断更新)
- 使用GDB调试产生多进程的程序
- 关于PV,流量和带宽
- Android上使用MP3格式录制声音
- 【数据分析】《深入浅出统计学》要点总结
- linux能不能装小狼毫输入法,小狼毫输入法如何设置?
- 大华NVR接入海康摄像机的设置
- 硬盘序列号更改工具 v0.1 下载
- macOS Windows版本 Photoshop 下载 AI下载
- Google Earth Engine简介
- ABBYY FineReader 14
- 分布式协调服务——Zookeeper入门
- 地理信息系统的元数据、主数据、参考数据之间的区分
- 计量经济学(stata)笔记1 记录每天的进步
- Python 使用can模块(记录稿)
- 微信CRM管理系统功能分析
- 千氪财经|2018 上半年币圈漏洞与攻击盘点
- Pikka 2.1.0 macOS菜单栏屏幕取色器
- php json_encode unicode,phpjson_encode总是返回unicode字符u.问题解决
- CSS特效-下雨天效果
热门文章
- javascript html注释,javascript html注释
- mathtype注册表
- 尚硅谷java——个人收支记录软件
- python生成三对角矩阵_块三对角矩阵python
- 面试官常问的web前端问题大全(10道面试真题祝你旗开得胜)
- 2018Web前端面试题及答案大全
- aliez歌词_aLIEz FULL歌词【假名 罗马音】
- hmcl启动器安装游戏版本失败_HMCL 启动器教程 #2 安装游戏版本、模组加载器与高清修复...
- [BZOJ 5339] 教科书般的亵渎
- 查看系统使用率命令 vmstat 输出详解!