Gray码

 

Gray码是一种数字编码方式,可以使相邻的两个数之间只有一位的差别。

构造格雷码的方式很简单,首先列出

0

1

以底部为水平轴在轴下方写出轴上方的反射,并在轴上方数字左边都加0,轴下方数字都加1:

00

01

11

10

这只是2位的表示0~3的Gray码,重复相同操作还可以得到:

000

001

011

010

110

111

101

100

通过这个方法,我们可以列出前2^n项数字的格雷码,用代码可以写成:

unsigned char *getGrayCodeList(int n) { unsigned char *num = (unsigned char *)malloc(sizeof(unsigned char) * (1 << n)); memset(num, 0, sizeof(unsigned char) * (1 << n)); int i, j, count = 2; num[0] = 0; num[1] = 1; for (i = 1; i < n; i++) { for (j = 0; j < count; j++) num[(count << 1) - 1 - j] = num[j]; count <<= 1; for (j = 0; j < (count >> 1); j++) *(num + j) &= ~(1 << i); for (;j < count; j++) *(num + j) |= (1 << i); } return num; } 

 

 

假设有4位二进制码abcd和格雷码efgh

因为二进制码abcd和Gray码之间有如下结论:

e = a

f = a ^ b

g = b ^ c

h = c ^ d

 

a = e

b = e ^ f

c = e ^ f ^ g

d = e ^ f ^ g ^ h

 

所以有以下一些运算

把二进制码转换为格雷码:

unsigned char bin2gray(unsigned char num, int n) { unsigned char retval = 0; int i; retval |= (num & (1 << (n - 1))); for (i = n - 1; i > 0; i--) { retval |= ((((num & (1 << i)) >> i) ^ ((num & (1 << (i - 1))) >> (i - 1))) << (i - 1)); } return retval; } 

Gray码转换为二进制码:

 

unsigned char gray2bin(unsigned char num, int n) { unsigned char retval = 0; int i, last; retval |= (num & (1 << (n - 1))); last = (num >> (n - 1)) & 1; for (i = n - 2; i >= 0; i--) { last ^= ((num >> i) & 1); retval |= last << i; } return retval; } 

Gray码递增最简单的方法就是转换为二进制码递增后再转换为Gray码:

void gray_inc(unsigned char *num, int n) { *num = bin2gray(gray2bin(*num, n) + 1, n); }  

也有以下两种方法:

void gray_inc2(unsigned char *num, int n) { unsigned char b = gray2bin(*num, n) + 1; *num = (b ^ (b >> 1)); } void gray_inc3(unsigned char *num, int n) { unsigned char b = gray2bin(*num, n); *num = (*num ^ (~b & (b + 1))); } 

 

参考:《Hacker's Delight》by Henry S.Warren, Jr.

 

 

 

你可能感兴趣的:(c)