【算法】格雷码(Gray Code)与8421二进制码之间的转换算法 (LeetCode89)
1. 格雷码简介
格雷码跟8421码一样,也是一种对数字进行二进制编码的方法,只是编码方法跟常见的8421二进制编码方法不一样。
格雷码序列中,相邻的两个数字的二进制编码只有一位是不一样的,这种编码方式常用于较复杂的电路中。大家都知道二进制的 0/1
代表了电路的 开/关
,例如n位的二进制编码,有很多情况下电路需要遍历 0 ~ 2^n
的情况,在电路实现中就是用n位的电路的开关依次转换来实现。
由于8421二进制编码的 0 ~ 2^n
的序列,相邻的两个数的二进制相差会出现多位不一样,因此电路在遍历时就需要同时变更多位电路开关,而这种操作是需要时间的,在这个过程中就有可能出现中间的状态,从而出现错误的编码。
例如:
n = 3 的 8421 编码
i | 8421编码 |
---|---|
0 | 000 |
1 | 001 |
2 | 010 |
3 | 011 |
4 | 100 |
5 | 101 |
6 | 110 |
7 | 111 |
相邻两个数之间的二进制编码相差的不止1位,就会出现上面说的情况。而格雷码编码中,相邻的两个数的二进制编码只有1位是不一样的,因此在物理电路的变换中只涉及到一位电路的开关操作,即操作是原子的
,不会出现中间过程,也就不会出现错误编码了,因此在某些场景的电路信号中被广泛运用。
2. 格雷码与8421二进制码之间的转换
以 n = 3
为例,8421码与格雷码之间的对应关系如下:
格雷码也是以全0开头的
i | 8421编码 | 格雷码 |
---|---|---|
0 | 000 | 000 |
1 | 001 | 001 |
2 | 010 | 011 |
3 | 011 | 010 |
4 | 100 | 110 |
5 | 101 | 111 |
6 | 110 | 101 |
7 | 111 | 100 |
2.1 8421码 ==> 格雷码
算法
1、8421码最左边一位不变,保留下来成为格雷码的最左边一位;
2、从左边第二位开始,将8421码的每一位与它左边的一位相 异或
得到对应位的格雷码;
代码实现
public static int toGrayCode(int i) {return i ^ (i >> 1);
}
将 i
与 i - 1
异或,也即将 i 的每一位与它的左边一位相异或。右移操作左边是补的0,0与任何数异或等于其本身,因此最左边一位被保留了。
2.2 格雷码 ==> 8421码
算法
1、格雷码的最左边一位保持不变,保留下来成为8421码的最左边一位;
2、从左边第二位开始,将格雷码的每一位与前一位计算得到的8421码 异或
得到当前的8421码;
解释
8421码转格雷码是通过 i ^ (i - 1) 实现的,要想将格雷码转换为8421码,我们知道,异或运算有如下性质:
(a ^ b) ^ b = a ^ (b ^ b) = a因此,可以得到 (i ^ (i >> 1)) ^ (i >> 1) = i ^ ((i >> 1) ^ (i >> 1)) = i
所以在上面的算法中在计算当前位的8421码时,需要将当前位的格雷码与上一位计算得到的8421码异或。
代码实现
public static int toBinaryCode(int grayCode, int n) {String grayCodeStr = Integer.toBinaryString(grayCode);if (grayCodeStr.length() < n) {// 补齐0,使得二进制编码有n位int bitCnt = grayCodeStr.length();for (int i = bitCnt; i < n; i++) {grayCodeStr = "0" + grayCodeStr;}}StringBuilder binary = new StringBuilder();binary.append(grayCodeStr.charAt(0)); //最左边一位不变for (int i = 1; i < n; i++) {char cur = grayCodeStr.charAt(i);char preBinary = binary.charAt(i - 1);int tmp = (cur - '0') ^ (preBinary - '0');if (tmp == 0) binary.append('0');else binary.append('1');}return Integer.parseInt(binary.toString(), 2);
}
2.3 测试
public class Demo {public static void main(String[] args) {int n = 3;int powN = (int) Math.pow(2, n);int[] grayCode = new int[powN];System.out.println("========= Binary to GrayCode ==========");for (int i = 0; i < powN; i++) {grayCode[i] = toGrayCode(i);System.out.print(grayCode[i] + " ");}System.out.println();System.out.println("========= GrayCode to Binary ==========");for (int i = 0; i < powN; i++) {int binary = toBinaryCode(grayCode[i], n);System.out.print(binary + " ");}System.out.println();}public static int toGrayCode(int i) {return i ^ (i >> 1);}public static int toBinaryCode(int grayCode, int n) {String grayCodeStr = Integer.toBinaryString(grayCode);if (grayCodeStr.length() < n) {// 补齐0,使得二进制编码有n位int bitCnt = grayCodeStr.length();for (int i = bitCnt; i < n; i++) {grayCodeStr = "0" + grayCodeStr;}}StringBuilder binary = new StringBuilder();binary.append(grayCodeStr.charAt(0)); //最左边一位不变for (int i = 1; i < n; i++) {char cur = grayCodeStr.charAt(i);char preBinary = binary.charAt(i - 1);int tmp = (cur - '0') ^ (preBinary - '0');if (tmp == 0) binary.append('0');else binary.append('1');}return Integer.parseInt(binary.toString(), 2);}
}
可以看到二进制与格雷码之间是可以正确转换的。
参考文献
[1] https://baike.baidu.com/item/%E6%A0%BC%E9%9B%B7%E7%A0%81/6510858?fr=aladdin#5
[2] https://leetcode.com/problems/gray-code/
【算法】格雷码(Gray Code)与8421二进制码之间的转换算法 (LeetCode89)相关推荐
- gray code java_格雷码Gray Code详解
格雷码简介 在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code),另外由于最大数与最小数之间也仅一位数不同,即"首尾相连",因此又 ...
- 二进制格雷码与自然二进制码之间的转换
什么是格雷码? 格雷码,又叫循环二进制码或反射二进制码,格雷码是我们在工程中常会遇到的一种编码方式,它的基本的特点就是任意两个相邻的代码只有一位二进制数不同. 二进制格雷码与自然二进制码的互换 1.二 ...
- 常用的几种在线地图(天地图、百度地图、高德地图)坐标系之间的转换算法
1.首先弄明白几种在线地图的坐标系: (1)天地图:CGCS2000,2000国家大地坐标系:我们其实很多时候直接用WGS84的坐标来代替CGCS2000坐标.因为CGCS2000的定义与WGS84实 ...
- Java 算法 格雷码
目录标题 题目描述 解题思路 代码 题目描述 格雷码是以n位的二进制来表示数. 与普通的二进制表示不同的是,它要求相邻两个数字只能有1个数位不同. 首尾两个数字也要求只有1位之差. 有很多算法来生成格 ...
- LeetCode(89):格雷编码 Gray Code(Java)
2019.7.19 #程序员笔试必备# LeetCode 从零单刷个人笔记整理(持续更新) 智力题,本题的关键在于搞清楚格雷编码的生成过程, G(i) = i ^ (i/2). 如 n = 3: G( ...
- 火星坐标和百度坐标之间的转换算法
在开始这个题目之前,先给大家再次扫扫盲,扫的不是坐标系统的盲,而是我们国家所使用的坐标系统.大家都知道,美国GPS使用的是WGS84的坐标系统,以经纬度的形式来表示地球平面上的某一个位置,这应该是国际 ...
- 计组——定点数原码反码补码移码以及它们之间的转换
原码 用尾数表示真值的绝对值,符号位"0/1"对应"正/负" 若机器字长n+1位,原码整数的表示范围:−(2n−1)≤x≤2n−1{\color{Red} -( ...
- Gray Code(格雷码) C++多方法实现
简介 在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code),另外由于最大数与最小数之间也仅一位数不同,即"首尾相连",因此又称循环 ...
- 格雷码与普通二进制码的相互转换——学习笔记
文章目录 格雷码 普通二进制码转换成格雷码 格雷码转换成普通二进制码 进一步 Reference 文章中内容与图片大部分来自Reference,本文只是以方便自己理解的方式进行整理. 格雷码 在一组数 ...
- 4位格雷码的顺序编码_格雷码那点事——递归非递归实现
简介 在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code),另外由于最大数与最小数之间也仅一位数不同,即"首尾相连",因此又称循环 ...
最新文章
- 5个常用Java代码混淆器 助你保护你的代码
- postgresql基本操作
- 远程连接linux(Ubuntu配置SSH服务)22端口
- QT的QAction类的使用
- RHCS创建高可用集群apche服务器
- python 文本文件处理_53 Python - txt普通文件处理
- html盒子居中的方式,CSS盒子居中三种方法
- 微软要放弃Edge了?传微软正在构建基于Chromium的浏览器
- java 封装log4j_Java项目 切片实现log4j的终极封装
- apt-cyg 代理设置
- FlashBuilder 4.6 破解序列号和方法
- 迅雷的php文件_使用迅雷下载.php文件的方法(Picjumbo可用)
- 用Python设计杂志订阅系统
- 自定义 QGraphicsItem
- macos安装盘第三方工具制作_如何制作macOS High Sierra USB启动安装盘
- 简单的MediaPlayer+SurfaceView实现视频横竖屏播放
- QUASI-HYPERBOLIC (拟双曲线) MOMENTUM AND ADAM FOR DEEP LEARNING——精读
- 超写实虚拟人制作教程
- 955 不加班公司名单:955.WLB
- Oracle Cloud(甲骨文)开启root登录
热门文章
- 幼儿园计算机游戏,幼儿园数学游戏大全(大中小班都有),不可错过!
- matlab版本下载地址
- Linux时间戳和标准时间的互转
- linux终端怎么复制粘贴某一行_超级小白帖:如何在Linux终端中复制粘贴
- 数据库实验一——数据定义
- Topic 19. 临床预测模型之输出每个患者列线图得分 (nomogramFormula)
- 手把手教你使用stata进行cox回归并制作列线图
- 【每天学一点新知识】getshell???webshell???
- C++和ASM文件的互相调用
- 编译报错:无法打开包括文件 No such file or directory