C语言格雷码相关
2016-04-03 15:41
323 查看
这几天做了几家公司的模拟在线测评题,均有关于格雷码的相关知识,有好一部分要运用到二进制与位运算,这些我都不太熟,今天趁格雷码把这些知识都记录一下。
在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code),另外由于最大数与最小数之间也仅一位数不同,即“首尾相连”,因此又称循环码或反射码。在数字系统中,常要求代码按一定顺序变化。例如,按自然数递增计数,若采用8421码,则数0111变到1000时四位均要变化,而在实际电路中,4位的变化不可能绝对同时发生,则计数中可能出现短暂的其它代码(1100、1111等)。在特定情况下可能导致电路状态错误或输入错误。使用格雷码可以避免这种错误。格雷码有多种编码形式。
如果要产生n位元的格雷码,那么格雷码的个数为2^n。当初这里看错了以为是2n,后来重新设计了一个函数计算2^n,才把问题解决。
设计方法:
第一步:产生 0, 1 两个字符串。
第二步:在第一步的基础上,每一个字符串都加上0和1,但是每次只能加一个,所以得做两次。这样就变成了 00,01,11,10 (注意对称)。
第三步:在第二步的基础上,再给每个字符串都加上0和1,同样,每次只能加一个,这样就变成了 000,001,011,010,110,111,101,100。
好了,这样就把3位元格雷码生成好了。
如果要生成4位元格雷码,我们只需要在3位元格雷码上再加一层0,1就可以了: 0000,0001,0011,0010,0110,0111,0101,0100,1100,1101,1110,1010,0111,1001,1000.
也就是说,n位元格雷码是基于n-1位元格雷码产生的。
下面是代码,利用递归来生成n位格雷码。
通过这题顺便了解了一下C语言里是如何输出二进制的,也同时复习了一下位运算的相关用法。首先对两串二进制代码用异或运算^,得到一个新的二进制代码,再对新的代码用(1 << i)的方式逐位用与运算&。
这里有个小地方需要注意一下,与运算以后的结果不可直接输出,应该判断结果是否为0,不为0输出1,否则输出0。
具体代码如下:
格雷码的生成
相邻格雷码之间只有一位不同,这是为了防止转换时多位同时变化而造成的延时的影响。具体定义如下。在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code),另外由于最大数与最小数之间也仅一位数不同,即“首尾相连”,因此又称循环码或反射码。在数字系统中,常要求代码按一定顺序变化。例如,按自然数递增计数,若采用8421码,则数0111变到1000时四位均要变化,而在实际电路中,4位的变化不可能绝对同时发生,则计数中可能出现短暂的其它代码(1100、1111等)。在特定情况下可能导致电路状态错误或输入错误。使用格雷码可以避免这种错误。格雷码有多种编码形式。
如果要产生n位元的格雷码,那么格雷码的个数为2^n。当初这里看错了以为是2n,后来重新设计了一个函数计算2^n,才把问题解决。
设计方法:
第一步:产生 0, 1 两个字符串。
第二步:在第一步的基础上,每一个字符串都加上0和1,但是每次只能加一个,所以得做两次。这样就变成了 00,01,11,10 (注意对称)。
第三步:在第二步的基础上,再给每个字符串都加上0和1,同样,每次只能加一个,这样就变成了 000,001,011,010,110,111,101,100。
好了,这样就把3位元格雷码生成好了。
如果要生成4位元格雷码,我们只需要在3位元格雷码上再加一层0,1就可以了: 0000,0001,0011,0010,0110,0111,0101,0100,1100,1101,1110,1010,0111,1001,1000.
也就是说,n位元格雷码是基于n-1位元格雷码产生的。
下面是代码,利用递归来生成n位格雷码。
#include <stdio.h> #include <string.h> #define MAX_LEN 256 char GrayCode[MAX_LEN][MAX_LEN]; //2 ^ n int pow(int m) { int i, sum = 2; if(1 == m) { return 2; } for(i = 1; i < m; i++) { sum *= 2; } return sum; } char** GrayCodeCreate(int n) { int i, j; if(1 > n) { printf("Wrong!\n"); return **GrayCode; } else if(1 == n) { //printf("%d ", strlen(GrayCode[0])); GrayCode[0][0] = '0'; GrayCode[1][0] = '1'; //printf("%d ", strlen(GrayCode[0])); return **GrayCode; } GrayCodeCreate(n - 1); for(i = pow(n) / 2 - 1, j = pow(n) / 2; i >= 0, j < pow(n); i--, j++) { strcpy(GrayCode[j], GrayCode[i]); } for(i = 0, j = pow(n) / 2; i < pow(n) / 2, j < pow(n); i++, j++) { GrayCode[i][strlen(GrayCode[i])] = '0'; GrayCode[j][strlen(GrayCode[j])] = '1'; } return **GrayCode; } int main() { int i, j, n; scanf("%d", &n); //printf("%d ", pow(n)); GrayCodeCreate(n); for(i = 0; i < pow(n); i++) { for(j = strlen(GrayCode[i]) - 1; j >= 0; j--) { putchar(GrayCode[i][j]); } printf("\n"); } return 0; }
判断是否可以以格雷码的方式排列
给出两个8位二进制代码,判断这两个代码可否以格雷码的方式连续排列。换个问法就是这两个二进制代码是否只有一位的区别。通过这题顺便了解了一下C语言里是如何输出二进制的,也同时复习了一下位运算的相关用法。首先对两串二进制代码用异或运算^,得到一个新的二进制代码,再对新的代码用(1 << i)的方式逐位用与运算&。
这里有个小地方需要注意一下,与运算以后的结果不可直接输出,应该判断结果是否为0,不为0输出1,否则输出0。
具体代码如下:
#include <stdio.h> #include <stdlib.h> int ShowInBinary(char term) { int i; int j; for(i = 7; i >= 0; i--) { j = (term & (1 << i)); if(j) { printf("1"); } else { printf("0"); } } printf("\n"); return 0; } int IsGrayOrNot(char term1, char term2) { char ch = term1 ^ term2; int i, j, count = 0; for(i = 7; i >= 0; i--) { j = ch & (1 << i); if(1 == j) { count++; } } if(count) return 1; //ShowInBinary(ch); return 0; } int main() { char term1 = 0x9d; char term2 = 0x9e; printf("%d", IsGrayOrNot(term1, term2)); //ShowInBinary(term1); //ShowInBinary(term2); return 0; }
相关文章推荐
- C语言(三眼怪物)
- C++变量初始化顺序
- 20160403_C++初始化列表与赋值
- Visual C++笔记
- 大数乘法(C语言实现)
- c++之函数特性 重载 内联 函数默认值
- c++ 和 C#类型对照
- 29.C语言字符串和字符数组
- STL学习笔记— —STL简述
- 二叉搜索树的一些操作的C++实现
- 静态和动态顺序表的实现(c语言)
- c++之初步学习
- C++ Standard-Library Random Numbers
- c++ 初学者写的图书馆管理系统 多多指教
- 1142: 【C语言训练】立方和不等式
- 简析四大函数
- C++中的复制构造函数
- 1133: 【C语言训练】求1+2!+3!+...+N!的和
- c++primer第二章读书笔记---变量和基本类型
- c++中动态尾随内存的技巧和定位new