文章目录

  • 1. 格雷码的应用意义
  • 2. 由自然数编码获得格雷码
    • 2.1 对称法实现
    • 2.2 公式法实现
  • 3. 由格雷码解码获得自然数

1. 格雷码的应用意义

学过晶体管知识的朋友们都知道,数据位跳变就相当于硬件电路中的晶体管翻转。许多位同时跳变就相当于多个晶体管同时翻转,会导致电路中出现很大的尖峰电流脉冲,从而导致数据不稳定

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

其重要特征是一个数变为相邻的另一个数时,只有一个数据位发生跳变,由于这种特点,就可以避免电路中出现亚稳态而导致数据错误。简而言之,格雷码的一位改变特征减小了电路出错概率,实际很多场合也用到了格雷码。

四位格雷码如下图所示:

更多内容,可见百度百科「格雷码」。



2. 由自然数编码获得格雷码

leetCode当中关于格雷码的生成有:89. 格雷编码、1238. 循环码排列


2.1 对称法实现

当是 0 0 0位格雷码时,格雷码序列即为 [ 0 ] [0] [0]。

如果我们获取了 n − 1 n-1 n−1位格雷码序列,并记为 G n − 1 G_{n-1} Gn−1​,可以使用它构造获得 n n n位格雷码序列 G n G_n Gn​。具体方法如下:

  • 将 G n − 1 G_{n-1} Gn−1​复制一份并进行反转,记为 G n − 1 T G_{n-1}^T Gn−1T​;
  • 将 G n − 1 T G_{n-1}^T Gn−1T​中每个元素的第 n − 1 n-1 n−1个二进制位均从 0 0 0变为 1 1 1,得到 ( G n − 1 T ) ′ (G_{n-1}^T)' (Gn−1T​)′。这里最低的二进制位为第 0 0 0个二进制位;
  • 将 G n − 1 G_{n-1} Gn−1​和 ( G n − 1 T ) ′ (G_{n-1}^T)' (Gn−1T​)′进行拼接,得到 G n G_n Gn​。

证明如下:

  • 由于 G n − 1 G_{n-1} Gn−1​是 [ 0 , 2 ( − 1 ) [0, 2^{(-1}) [0,2(−1)的排列,那么其中每个元素的第 n − 1 n-1 n−1个二进制位都是 0 0 0。进而, ( G n − 1 T ) ′ (G_{n-1}^T)' (Gn−1T​)′是 [ 2 n − 1 , 2 n ) [2^{n-1}, 2^{n}) [2n−1,2n)的排列,所以 G n = G n − 1 + ( G n − 1 T ) ′ G_n=G_{n-1}+(G_{n-1}^T)' Gn​=Gn−1​+(Gn−1T​)′就是 [ 0 , 2 n ) [0,2^n) [0,2n)的排列;
  • 对于 G n − 1 G_{n-1} Gn−1​和 ( G n − 1 T ) ′ (G_{n-1}^T)' (Gn−1T​)′的内部,每对相邻整数的二进制恰好有一位不同。对于 G n − 1 G_{n-1} Gn−1​最后一个数和 ( G n − 1 T ) ′ (G_{n-1}^T)' (Gn−1T​)′第一个数,它们只有第 n − 1 n-1 n−1个二进制位不同。对于 G n − 1 G_{n-1} Gn−1​第一个数和 ( G n − 1 T ) ′ (G_{n-1}^T)' (Gn−1T​)′最后一个数,它们也仅有第 n − 1 n-1 n−1个二进制位不同。

因此, G n G_n Gn​就是满足要求的 n n n位格雷码序列。对应的cpp代码为:

class Solution {public:vector<int> grayCode(int n) {vector<int> ans;ans.push_back(0);for (int i = 1; i <=n; ++i) {int t = ans.size();for (int j = t-1; j >= 0; --j) {//ans.push_back(ans[j] + (1 << (i-1)));//这里+,|运算等效,因为0|A=A,且这里是按位或ans.push_back(ans[j] | (1 << (i-1)));}}return ans;}
};

2.2 公式法实现

也可以由公式直接求出,第 i ( i ≥ 0 ) i(i\ge0) i(i≥0)个格雷码为: g i = i ⊕ ⌊ i 2 ⌋ g_i=i\oplus\lfloor\frac{i}{2}\rfloor gi​=i⊕⌊2i​⌋

其中 ⊕ \oplus ⊕表示按位异或运算,正确性证明如下:

  • 当 i i i为偶数时, i i i和 i + 1 i+1 i+1只有最低的一个二进制位不同,而 ⌊ i 2 ⌋ \lfloor\frac{i}{2}\rfloor ⌊2i​⌋和 ⌊ i + 1 2 ⌋ \lfloor\frac{i+1}{2}\rfloor ⌊2i+1​⌋相等,进而异或之后 g i g_i gi​和 g i + 1 g_{i+1} gi+1​也只有最低的一个二进制位不同;
  • 当 i i i为奇数时,我们记 i i i的二进制表示为 ( ⋯ 01 ⋯ 11 ) 2 (⋯01⋯11)_2 (⋯01⋯11)2​, i + 1 i+1 i+1 的二进制表示为 ( ⋯ 10 ⋯ 00 ) 2 (⋯10⋯00)_2 (⋯10⋯00)2​,即:
    • i i i和 i + 1 i+1 i+1的二进制表示的若干个最高位是相同的;
    • i i i和 i + 1 i+1 i+1的二进制表示的从高到低的第一个不同的二进制位, i i i中的二进制为 0 0 0, i + 1 i+1 i+1中的二进制位则为 1 1 1,在此之后, i i i中的二进制均为 0 0 0, i + 1 i+1 i+1中的二进制位均为 1 1 1;
    • 那么 ⌊ i 2 ⌋ \lfloor\frac{i}{2}\rfloor ⌊2i​⌋和 ⌊ i + 1 2 ⌋ \lfloor\frac{i+1}{2}\rfloor ⌊2i+1​⌋的二进制表示分别为 ( ⋯ 01 ⋯ 1 ) 2 (⋯01⋯1)_2 (⋯01⋯1)2​和 ( ⋯ 10 ⋯ 0 ) 2 (⋯10⋯0)_2 (⋯10⋯0)2​,进而有: g i = ( ⋯ 01 ⋯ 11 ) 2 ⊕ ( ⋯ 10 ⋯ 0 ) 2 = ( ⋯ 010 ⋯ 0 ) 2 g_i=(⋯01⋯11)_2\oplus(⋯10⋯0)_2=(⋯010⋯0)_2 gi​=(⋯01⋯11)2​⊕(⋯10⋯0)2​=(⋯010⋯0)2​,以及: g i + 1 = ( ⋯ 10 ⋯ 00 ) 2 ⊕ ( ⋯ 10 ⋯ 0 ) 2 = ( ⋯ 110 ⋯ 0 ) 2 g_{i+1}=(⋯10⋯00)_2\oplus(⋯10⋯0)_2=(⋯110⋯0)_2 gi+1​=(⋯10⋯00)2​⊕(⋯10⋯0)2​=(⋯110⋯0)2​,也只有一个二进制位不同。
    • 注意到,当我们在表示 i + 1 i+1 i+1时,使用的的是 ( ⋯ 10 ⋯ 00 ) 2 (⋯10⋯00)_2 (⋯10⋯00)2​ ,默认了其二进制表示的低位至少有两个 0 0 0。事实上,当 i + 1 i+1 i+1 是 2 2 2的倍数而不是 4 4 4的倍数时,结论相同。
class Solution {public:vector<int> grayCode(int n) {vector<int> ret(1 << n);for (int i = 0; i < ret.size(); ++i) ret[i] = (i >> 1) ^ i;return ret;}
};

也即二进制到格雷码转换的固定规律为:

  • 格雷码中的最高有效位(最左边)等同于二进制数中相应的最高有效位;
  • 从左到右,加上每一对相邻的二进制编码位,从而得到下一个格雷码位,舍去进位。


3. 由格雷码解码获得自然数

格雷码到二进制转换的固定规律为:

  • 二进制码的最高有效位(最左边)等同于格雷码中相应的最高有效位。
  • 将所产生的每个二进制码位加下一个相邻位置的格雷码位,从而得到下一个二进制位。舍去进位。

/*解码模板 */
#include<math.h>      // log对数函数需要用到的头文件
#include <iostream>
using namespace std;int gray_decode(int num) {int head;if (!num) return 0;head = 1 << int(log(num) / log(2));    //C++没有直接以2为底的对数,我们创造一个以2为底的对数return head + gray_decode((num^head) ^ (head>>1));
}

格雷码应用意义及编解码相关推荐

  1. Python基于二维码实现的在线编解码系统

    目 录 摘 要 I Abstract II 第一章 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 工作环境和背景 2 1.3.1 操作系统 3 1.3.2 编程语言 3 1.3.3编码 ...

  2. H.264码流分析及编解码调试

    一.H.264码流分析 1. 选择一个.mp4或者.264文件. 2. 在码流分析仪软件中打开该文件,从几个层次进行分析: (1) 分析SPS和PPS里都包含哪些主要的信息,给出参数值.(例如分辨率. ...

  3. 高速理解掌握node.js 字符编码,确码过程 以及base64编解码原理

    var buf1 = new Buffer('a','ascii'); // 字符'a' -> ascii编码 -> 61 存在计算机中 console.log(buf1);var b = ...

  4. OpenCV解码格雷码模式

    OpenCV解码格雷码模式 解码格雷码模式 目标 代码 解释 解码格雷码模式 目标 在本教程中,您将学习如何使用GrayCodePattern类来: 解码先前获取的格雷码图案. 生成视差图. 生成一个 ...

  5. 网页直播源码与编解码

    在网页直播源码开发过程中我们一定会涉及到音视频压缩编码知识,压缩编码过程是一种有损的压缩,它的目的是减少音视频文件所需占用的空间和带宽并提高兼容性,在此期间还要尽可能保障音视频"不失真&qu ...

  6. 格雷码基础和生成的几种方法

    1 格雷码: 1.1 格雷码引言: 在数字系统中,常要求代码按一定顺序变化. 在机器视觉里面,编码结构光也是按照一定的顺序进行变化,最常用的就是Binary,但是,二进制的纯粹的编码,由于二进制的进制 ...

  7. C++ 数学与算法系列之认识格雷码

    1. 前言 程序中所涉及到的任何数据,计算机底层均需转换成二进制数值后方可存储,这个过程也称为编码.反之,把底层二进制数据转换成应用数据称为解码, 不同的数据类型需要不同的编(解)码方案,如音频数据编 ...

  8. 新一代图片编解码技术在淘宝的应用及落地

    本文回顾淘宝图片发展的历史,阐述了新一代图像编解码格式AVIF在淘宝业务场景中的应用及落地方案,节省流量,为用户提供更好的看图体验. 背景 淘宝图片空间下行链路承载着集团图片的访问请求,包括手淘.飞猪 ...

  9. (推荐阅读)H264, H265硬件编解码基础及码流分析

    需求 在移动端做音视频开发不同于基本的UI业务逻辑工作,音视频开发需要你懂得音视频中一些基本概念,针对编解码而言,我们必须提前懂得编解码器的一些特性,码流的结构,码流中一些重要信息如sps,pps,v ...

最新文章

  1. swift 如何实现点击view后显示灰色背景
  2. Dataset之Boston:Boston波士顿房价数据集的简介、下载、使用方法之详细攻略
  3. 【深入Java虚拟机JVM 01】Java发展与展望概述
  4. linux下ftp服务器搭建详解
  5. iOS中的应用启动原理
  6. PyCharm 安装插件
  7. mysql模糊查询 or_mysql 模糊查询 - yizhichao的个人页面 - OSCHINA - 中文开源技术交流社区...
  8. shell 死循环if判断_一个简单的shell脚本问题!怎么出现了死循环呢?谢谢
  9. PAT 1012 数字分类
  10. 如何建立你的思科CCNP实验室
  11. 把服务器当网盘玩 教你从云服务器下载自己的文件
  12. python实现简单五子棋
  13. MySQL函数计算24小时平均浓度对应的IAQI和AQI
  14. random.seed(0)
  15. Consumer cannot be configured for auto commit for ackMode MANUAL_IMMEDIATE
  16. 【小游戏】Flappy bird
  17. 为什么大部分公司的数据库系统仍然要使用oracle?
  18. jitter单位_Jitter知识
  19. .NET框架-Try-Parse和Tester-Doer
  20. 专业的web打印插件

热门文章

  1. linux sed 冒号,Linux -sed
  2. mongo在哪创建管理员_【教育信息】均衡创建再加压,齐心合力攻难关!
  3. 左连接 ,右连接,内连接和全外连接的4者区别
  4. idea快捷键打开run的窗口_看了上篇文章,你不了解的IDEA操作……
  5. 【Java集合框架】22 ——SortedMap 接口
  6. iOS itunes 权限分配
  7. scss中的@each 指令
  8. 专注于自媒体短视频领域四年后的运营问题汇总-第二集
  9. Webpack-2:Webpack
  10. 电路交换、分组交换、ATM交换