格雷码的生成与解码

这篇具有很好参考价值的文章主要介绍了格雷码的生成与解码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code),另外由于最大数与最小数之间也仅一位数不同,即“首尾相连”,因此又称循环码或反射码。在数字系统中,常要求代码按一定顺序变化。例如,按自然数递增计数,若采用8421码,则数0111变到1000时四位均要变化,而在实际电路中,4位的变化不可能绝对同时发生,则计数中可能出现短暂的其它代码(1100、1111等) 。在特定情况下可能导致电路状态错误或输入错误。使用格雷码可以避免这种错误(格雷码一位改变特征减小了电路出错概率)。

格雷码有多种编码形式:

格雷码的生成与解码

表中典型格雷码具有代表性。若不作特别说明,格雷码就是指典型格雷码,它可从自然二进制码转换而来。

下面我们讨论怎么求格雷码(即典型格雷码):

 一、格雷码的生成

方法一:

若要生成n位(即2^n个)格雷码序列,我们首先从0开始:

第一步:改变最右边的位元的值,得到1;

第二步:改变右边起第一个为1位元的左边的那个位元,得到11

第三步:重复一、二步,直到生成要求个数的格雷码

按照上述步骤生成的序列即为格雷码。

eg:000 >> 001 >> 011 >> 010 >> 110 >> 111 >> 101 >> 100 ......

代码实现:

vector<int> getGrayCode(int n){//生成n位格雷码序列
	vector<int> ans;
	ans.emplace_back(0);
	int lenth = 1;//ans数组的长度
	while (lenth < (1 << n)) {
		if (lenth % 2)ans.emplace_back(ans[lenth - 1] ^ 1);//改变最右边的位元值
		else ans.emplace_back(ans[lenth - 1] ^ ((ans[lenth - 1] & -ans[lenth - 1]) << 1));
		//num & -num可以得到num中二进制最右边的1,然后再向左移一位
		lenth++;
	}
	return ans;
}

方法二:

通过观察可得出,如果我们可以得到n-1位格雷码序列,那么通过将n-1位格雷码序列逆转,再在逆转的格雷码序列的最左端都补上1,将得到的序列连接到原序列后即可得到n位格雷码序列。

eg:已有2位格雷码序列 00 01 11 10

        将原序列逆转得 10 11 01 00

        在左端补上1得110 111 101 100

        接到原序列后面得到3位格雷码 000 001 011 010 110 111 101 100

证明:已有n-1位格雷码序列,则可知n-1位格雷码序列逆序也满足相邻代码只有一位不同,且首尾相连,对逆序的所有代码左端补1不改变上述性质,将两段代码相接后连接处的两个代码只有最高位不同,首尾代码也只有最高位不同,所以得到的是n位格雷码。

代码实现:

vector<int> getGrayCode(int n){//生成n位格雷码序列
	vector<int> ans;
	ans.emplace_back(0);
	for (int i = 0; i < n; i++) {
		for (int j = ans.size() - 1; j >= 0; j--) {
			ans.emplace_back(ans[j] + (1 << i));
		}
	}
	return ans;
}

方法三:

通过自然二进制码得到格雷码

通过观察或者推理都可以得出,格雷码的最高位和自然二进制码的最高位是相同的

对n位二进制的码字,从右到左,以0到n-1编号,如果二进制码字的第i位和i+1位相同,则对应的格雷码的第i位为0,否则为1(当i+1=n时,二进制码字的第n位被认为是0,即第n-1位不变)

公式:格雷码的生成与解码

 (G:格雷码,B:二进制码)

格雷码的生成与解码

上图中0^b3 == b3,相当于保留b3

若当前二进制码为奇数  xp01111(x表示任意长度的前缀,p可能是0也可能是1)

则下一位二进制码为  xp10000 (它们的前缀相同) 

根据上述公式,上面两个二进制码只有p^0和p^1会产生不同的结果,所以满足生成的相邻的格雷码只有一位二进制数不同,同理最后一位二进制码111...1生成的格雷码100...0与头部格雷码也只有一位不同,满足首尾相连。

代码实现:

vector<int> getGrayCode(int n){//生成n位格雷码序列
	vector<int> ans;
	for (int i = 0; i < (1 << n); i++) {
		ans.emplace_back(i ^ (i >> 1));
		cout << bitset<4>(ans[i]) << endl;
	}
	return ans;
}

根据代码可得该公式也可写为:gi = i ^ (i / 2);其中i / 2向下取整。gi是序列中第i个格雷码。

二、格雷码的解码

即得到格雷码后如何将其转化为对应的二进制码。

从左边第二位起,将每位与左边一位解码后的值异或,作为该位解码后的值(最左边一位依然不变)。依次异或,直到最低位。依次异或转换后的值(二进制数)就是格雷码转换后二进制码的值。

公式:格雷码的生成与解码

 (G:格雷码,B:二进制码) 

下面是我对公式的一些推导:

格雷码的生成与解码

格雷码相关例题:

题一

题二文章来源地址https://www.toymoban.com/news/detail-488908.html

到了这里,关于格雷码的生成与解码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • FPGA——verilog实现格雷码与二进制的转换

    格雷码是一种循环二进制码或者叫作反射二进制码。跨时钟域会产生亚稳态问题(CDC问题):从时钟域A过来的信号难以满足时钟域B中触发器的建立时间和保持时间,输入与clk的变化不同步而导致了亚稳态。此时触发器输出端Q在有效时钟沿之后比较长的一段时间处于不确定的

    2024年02月15日
    浏览(59)
  • verilog手撕代码5——计数器(置位、加减、环形、扭环形、格雷码计数器实现)

    2023.5.12 编写一个十六进制计数器模块,计数器输出信号递增每次到达0,给出指示信号 zero ,当置位信号 set 有效时,将当前输出置为输入的数值 set_num 。 注意 :这里zero=1和num=0是同一拍输出的,按道理如果根据num=0,然后去输出zero=1应该延迟一拍。所以这里考虑将number延迟一

    2024年02月07日
    浏览(54)
  • 10.31一些代码分析,香浓展开,移位器(桶形多位),二进制转格雷码

     always的block之间,采用并行执行 always之内,采用非阻塞赋值,为顺序执行 这个把使能信号和W信号组合在一起,进行case语句,即只有合并信号最高位为1时,才进行操作 always后面要写@,assign不用 这没有期望的边沿,就是只要发生变化就会触发 加上posedge,negedge就可以标记期望

    2024年02月07日
    浏览(60)
  • 算法leetcode|89. 格雷编码(rust重拳出击)

    n 位格雷码序列 是一个由 2 n 个整数组成的序列,其中: 每个整数都在范围 [0, 2 n - 1] 内(含 0 和 2 n - 1) 第一个整数是 0 一个整数在序列中出现 不超过一次 每对 相邻 整数的二进制表示 恰好一位不同 ,且 第一个 和 最后一个 整数的二进制表示 恰好一位不同 给你一个整数

    2024年02月04日
    浏览(45)
  • 数据结构与算法之数组: Leetcode 89. 格雷编码 (Typescript版)

    格雷编码 https://leetcode.cn/problems/gray-code/ 描述 n 位格雷码序列 是一个由 2n 个整数组成的序列,其中: 每个整数都在范围 [0, 2n - 1] 内(含 0 和 2n - 1) 第一个整数是 0 一个整数在序列中出现 不超过一次 每对 相邻 整数的二进制表示 恰好一位不同 ,且 第一个 和 最后一个 整数

    2024年02月02日
    浏览(43)
  • C/C++每日一练(20230221) 格雷编码、矩阵问题、搜索旋转排序数组II

    目录 1. 格雷编码 2. 矩阵问题 3. 搜索旋转排序数组 II 格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异。 给定一个代表编码总位数的非负整数  n ,打印其格雷编码序列。即使有多个不同答案,你也只需要返回其中一种。 格雷编码序列必须

    2024年02月16日
    浏览(54)
  • 快速生成一组环形数据

       sklearn是一个开源的机器学习库,支持不同种类的机器学习算法,并且提供了许多质量良好的数据集。假如我们想要得到一组环形数据集,借助sklearn的包很轻易就可以实现,不过换个角度思考,我们自己动手是否也可以生成一组数据,使之在散点图上环状分布;借助C++的

    2024年02月05日
    浏览(40)
  • opensl学习——base16编码解码、base64编码解码、ASCII码表、扩展ASCII码

    ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是一套基于拉丁字母的字符编码,共收录了 128 个字符,用一个字节就可以存储,它等同于国际标准 ISO/IEC 646。 ASCII 编码于 1967 年第一次发布,最后一次更新是在 1986 年,迄今为止共收录了 128 个字符,包

    2024年02月07日
    浏览(49)
  • URL在线编码/解码工具

    一刀工具箱提供在线URL编码解码工具:对网址Url进行UrlEncode编码转换,UrlEncode编码,UrlDecode解码。  代码片段 URL在线编码/解码工具 - 一刀工具箱APP 一刀工具箱提供在线URL编码解码工具:对网址Url进行UrlEncode编码转换,UrlEncode编码,UrlDecode解码。 https://tools.yidaotool.com/encode

    2024年02月11日
    浏览(49)
  • 解码器 | 基于 Transformers 的编码器-解码器模型

    基于 transformer 的编码器-解码器模型是 表征学习 和 模型架构 这两个领域多年研究成果的结晶。本文简要介绍了神经编码器-解码器模型的历史,更多背景知识,建议读者阅读由 Sebastion Ruder 撰写的这篇精彩 博文。此外,建议读者对 自注意力 (self-attention) 架构 有一个基本了解

    2024年02月08日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包