格雷码简介及格雷码与二进制的转换程序

格雷码简介

格雷码(英文: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语言编程,格雷码简介及格雷码与二进制的转换程序相关推荐

  1. 51单片机二进制转bcd码c语言,16位二进制数转换成BCD码的的快速算法-51单片机...

    在做而论道上篇博文中,回答了一个16位二进制数转换成BCD码的问题,给出了一个网上广泛流传的经典转换程序. . 说它经典,不仅是因为它已经流传已久,重要的是它的编程思路十分清晰,十分易于延伸推广.做而 ...

  2. mysql创建表里主码和外码_SQL语言创建表时候怎么定义主码和外码

    展开全部 SQL语言62616964757a686964616fe58685e5aeb931333433623064创建表时候用Primary Key(属性名)定义主码,用Foreign Key(属性 ...

  3. c语言 补码转原码,C语言编程之二进制原码、反码和补码

    概述 在计算机内,有符号数有3种表示法:原码.反码和补码. 在计算机中,数据是以补码的形式存储的,所以补码在c语言的教学中有比较重要的地位,而讲解补码必须涉及到原码.反码. 详细释义 所谓原码就是二进 ...

  4. c语言能让制表符空9个字符码,C语言编程规范 – 嗨!大佟!

    1. 背景 无论如何,标准是团队开发的保证之一,而且标准欢迎争吵和变化.我们使代码易于管理的方法之一是增强代码一致性,让别人可以读懂你的代码是很重要的,保持统一编程风格意味着可以轻松根据"模 ...

  5. c语言数独程序源码,c语言编程:优化回溯解数独程序

    上次在博客上发了一篇<C语言:回溯解数独程序>.实在很粗糙,效率相当差.正如在群里一位朋友说的: 你能不能别像傻瓜式一样从左到右从上到下这样搜索呢?如果你这样,我出第一行是空的数独题,那你 ...

  6. c语言数组与指针编程源码,C语言编程(练习9:数组与指针)

    题目:有 5 个字符串,首先将它们按照字符串中的字符个数由小到大排列,再分别取出每个字符串的第三个字母合并成一个新的字符串输出(若少于三个字符的输出空格).要求:利用字符串指针和指针数组实现. 代码实 ...

  7. c#语言经典程序100例,C#入门必看的实例程序100个 - 源码下载|Windows编程|其他小程序|源代码 - 源码中国...

    C#入门必看的实例程序100个\实例01\01.bmp C#入门必看的实例程序100个\实例01\csc编译器路径.txt C#入门必看的实例程序100个\实例01\hello.cs C#入门必看的实 ...

  8. c语言门禁系统源代码,D01_门禁管理系统 - 源码下载|Windows编程|其他小程序|源代码 - 源码中国...

    文件名大小更新时间 D01_门禁管理系统\.vs\D01_门禁管理系统\v15\.suo204802019-05-28 D01_门禁管理系统\.vs\slnx.sqlite2375682019-05- ...

  9. c语言字符类型强制换成内码,C语言实现不同汉字系统的内码转换方法

    摹14●摹 1囊 l9髓 丰 3̂ 齐 弃 靖尔 大 学学 报 J伽rn|l 0fQiq 嘶 劬 q 言实现不 字 |I∈峰 张宏烈 周长支 一 1 / (齐弃暗拳太掌工鼍qb,一r /1 -i l ...

  10. C语言—编程机制(简介)_成仙不问道

    生成程序的具体过程因计算机环境而异. C编程机制:通过程序把源代码文件转换为可执行文件(其中包含可直接运行的机器语言代码).典型C实现通过编译和链接两个步骤来完成这一过程.编译器把源代码转换成中间代码 ...

最新文章

  1. babel css3新特性_前端总结(后续不断更新)
  2. 使用GDB调试产生多进程的程序
  3. 关于PV,流量和带宽
  4. Android上使用MP3格式录制声音
  5. 【数据分析】《深入浅出统计学》要点总结
  6. linux能不能装小狼毫输入法,小狼毫输入法如何设置?
  7. 大华NVR接入海康摄像机的设置
  8. 硬盘序列号更改工具 v0.1 下载
  9. macOS Windows版本 Photoshop 下载 AI下载
  10. Google Earth Engine简介
  11. ABBYY FineReader 14
  12. 分布式协调服务——Zookeeper入门
  13. 地理信息系统的元数据、主数据、参考数据之间的区分
  14. 计量经济学(stata)笔记1 记录每天的进步
  15. Python 使用can模块(记录稿)
  16. 微信CRM管理系统功能分析
  17. 千氪财经|2018 上半年币圈漏洞与攻击盘点
  18. Pikka 2.1.0 macOS菜单栏屏幕取色器
  19. php json_encode unicode,phpjson_encode总是返回unicode字符u.问题解决
  20. CSS特效-下雨天效果

热门文章

  1. javascript html注释,javascript html注释
  2. mathtype注册表
  3. 尚硅谷java——个人收支记录软件
  4. python生成三对角矩阵_块三对角矩阵python
  5. 面试官常问的web前端问题大全(10道面试真题祝你旗开得胜)
  6. 2018Web前端面试题及答案大全
  7. aliez歌词_aLIEz FULL歌词【假名 罗马音】
  8. hmcl启动器安装游戏版本失败_HMCL 启动器教程 #2 安装游戏版本、模组加载器与高清修复...
  9. [BZOJ 5339] 教科书般的亵渎
  10. 查看系统使用率命令 vmstat 输出详解!