格雷码生成

二进制码第n位 = 二进制码第(n+1)位+格雷码第n位。因为二进制码和格雷码皆有相同位数,所以二进制码可从最高位的左边位元取0,以进行计算。(注:遇到1+1时结果视为0)
例如: 格雷码0111,为4位数,所以其所转为之二进制码也必为4位数,因此可取转成之二进制码第五位为0,即0 b3 b2 b1 b0。
0+0=0,所以b3=0
0+1=1,所以b2=1
1+1取0,所以b1=0
0+1取1,所以b0=1
因此所转换为之二进制码为0101



https://zh.wikipedia.org/wiki/%E6%A0%BC%E9%9B%B7%E7%A0%81


#include <iostream>
#include <stdio.h>

using namespace std;

int main () {
	int i , t , a[50] , j;
	for ( i = 0 ; i < (1<<4) ; i++ ) {
		t = (i^(i>>1));
		for ( j = 4 ; j >= 1 ; j-- , t >>= 1 ) a[j] = t % 2;
		for ( j = 1 ; j <= 4 ; j++ ) cout << a[j];
		cout << endl;
	}
	return 0;
}


16.06.29 UPD

既然知道了计算公式,我们来简单证明一下。
求证:第i个格雷码=i^(i>>1)
证明:
首先考虑生成格雷码。
假设已经有了n-1位的格雷码,那么如下操作,把原格雷码镜像复制一遍,在前2^(n-1)个数前加0,后前2^(n-1)个数前加1。
除了第2^(n-1)个数和第2^(n-1)+1个数外,相邻两数都是只有一位不同,最后加的位数也是一样的所以满足格雷码的要求。第2^(n-1)个数和第2^(n-1)+1个数后n-1位是一样的,但是最高位不一样,也满足要求。

于是就生成了n位的格雷码。


观察这个操作,考虑右数第i位在2^n个格雷码中的情况。在前2^(i-1)个数中,并没有操作第i位,所以是0。之后进行镜像,第2^(i-1)+1个数到第2^i个数时第i位是1。再进行镜像,第2^i+1个数到第2^i+2^(i-1)个数是1,第2^i+2^(i-1)+1个数到第2^(i+1)个数是0。(这个好麻烦,不画图了。)

这样第i位就是回文串了,之后镜像等于重复这个串。
于是它的循环长度是2^(i+1),那么按k从小到大考虑第k个二进制数的第i位和第i+1位,在最开始,这两位都是0,异或起来是0。在k到了2^i至2^(i+1)-1时,第i位是1,第i+1位是0,异或为1。在k到了2^(i+1)至2^(i+1)+2^i-1时,第i位是0,第i+1位是1,异或为1。在k到了2^(i+1)+2^i至2^(i+2)-1时,第i位是1,第i+1位是1,异或为0。刚好与格雷码吻合。
之后k的第i位和第i+1位又变为0和0,循环长度也一样。
于是每一位都是对齐的,第i个格雷码=i^(i>>1)。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值