您的位置:首页 > 编程语言 > C语言/C++

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位格雷码。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: