完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
格雷码简介及格雷码与二进制的转换程序
格雷码简介 格雷码(英文: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 / %ldn",dTime,CLOCKS_PER_SEC); //------------------------------------------------------ cStart=clock(); for (input=0;input<9999999;input++) b2g(0,65535,32768); cEnd=clock(); dTime=(cEnd-cStart); printf("b2g: %ld / %ldn",dTime,CLOCKS_PER_SEC); //------------------------------------------------------ cStart=clock(); for (input=0;input<9999999;input++) GtoB(32768); cEnd=clock(); dTime=(cEnd-cStart); printf("GtoB: %ld / %ldn",dTime,CLOCKS_PER_SEC); //------------------------------------------------------ cStart=clock(); for (input=0;input<9999999;input++) g2b(0,65535,32768); cEnd=clock(); dTime=(cEnd-cStart); printf("g2b: %ld / %ldn",dTime,CLOCKS_PER_SEC); #else //程序演试部分 printf("Input(HEX):"); scanf("%x",&input); while (input!=-1) { printf("------BtoG------nBinary:%08XhnGray :%08Xhn------GtoB------nGray :%08XhnBinary:%08Xhn----------------n",input,BtoG(input),input,GtoB(input)); printf("Input(HEX):"); scanf("%x",&input); } #endif |
|
相关推荐
|
|
学习一下,谢谢楼主分享,十分感谢
|
|
|
|
|
|
786 浏览 0 评论
4210 浏览 0 评论
如何使用python调起UDE STK5.2进行下载自动化下载呢?
2520 浏览 0 评论
开启全新AI时代 智能嵌入式系统快速发展——“第六届国产嵌入式操作系统技术与产业发展论坛”圆满结束
2926 浏览 0 评论
获奖公布!2024 RT-Thread全球巡回线下培训火热来袭!报名提问有奖!
31442 浏览 11 评论
72901 浏览 21 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 05:36 , Processed in 0.391940 second(s), Total 36, Slave 28 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号