这是对特定格雷码单调排序(二进制反射格雷码)的简单测试:
// convert Gray code binary number to base 2 binary number
int Base2(byte Gray){ Gray^=Gray>>4; Gray^=Gray>>2; return Gray^=Gray>>1; }
// test if Gray codes are consecutive using "normal" base 2 numbers
boolean GraysAdjacent(byte x, byte y){ return 1 == abs(Base2(x)-Base2(y)); }
尤其是这个答案(最好的):
如何查找两个数字是否是格雷码序列中的连续数字
用 C 编码为:
int GraysTouch(byte x, byte y){ return !( (x^y ^ 1) && ( x^y ^ (y&-y)<<1 ) ); }
// test x marks the spots! (where they touch!)
for(int i=31; i>-1; --i )
for(int j=31; j>-1; --j )
Serial.print((String)(GraysTouch( i^i>>1, j^j>>1 )?"x":".") +
(GraysTouch( j^j>>1, i^i>>1 )?"X":".") + (j?"":"\n"));
这是如何工作的:......将被解释而不是OP 代码,因为它是高度可疑的(参见下面的警告评论)。
的一个属性XOR
,也就是^
运算符,是匹配的0
位是,不同的位是1
。
1^0 == 0^1 == 1
1^1 == 0^0 == 0
此外,对于一点,0 XOR b
作为恒等函数或简单地b
作为
1 XOR b
补充(请不要恭维)函数或~b
.
id(x) == x == x^0
opposite(x) == ~x == x^11111111 Why eight 1's? Are eight enough?
比较两个位串时XOR
,与 不同的位XOR
为1
,否则位必须匹配且XOR
为0
:
0101 0001111001100111000
XOR 0011 XOR 0001111001100000111
------ ---------------------
0110 0000000000000111111
这解释了x^y
上面代码的一部分。
-------------------------------------------------- --------------------
顺便说一句:
n^n>>1
将基数 2 二进制快速转换为此处使用的格雷码二进制数。
还要注意它对f(a,b)=a^b^b=a
任何人都是幂等的b
!
然后是就地交换a=a^b; b=a^b; a=a^b;
。
展开c=a^b; d=c^b; e=c^d;
即。d=a^b^b=a; e=a^b^a=b;
-------------------------------------------------- --------------------
现在,根据定义,对于两个相邻或连续的格雷编码数字,必须有一个且只有一个可以改变和不同的位。
例子:
Johnson
Code
000 000 000 000
001 001 001 100
011 101 011 110
111 111 010 010
110 011 110 011
100 010 111 111
110 101 101
100 100 001
^^^
this Gray coding
is the one used here
仔细检查。
情况1
当连续数的最低位,x
和y
,对于任何格雷码,都不同,其余的必须相同!这是格雷码的定义。这意味着x^y
必须看起来像 0000...0001。
还记得补码,~
函数aka1^b
吗?测试最后一位x^y
是XOR
'd with 1
。
这解释了x^y ^ 1
.
------------------------------------------
情况2
不同位在连续格雷码数字中的位置,x
并且y
不是最低位。仔细看看这些格雷码连续数字。
001 010 101 lower order bits all match
011 110 111
| | | <-- | mark location of lowest 1
010 100 010 <-- XOR's
有趣的是,在这个格雷码中,当最低位在x
和中匹配时,最低位y
的位置也是如此1
。
更有趣的是,对于连续的数字,在下一个更高位的位位置上的位总是不同的(对于这个格雷码) !
所以,x^y
看起来 ???...?1000...0
哪里1000...0
必须至少有一个 0,10
(为什么?)并且???...?
是连续格雷码数字必须是的神秘位000...0
。(为什么?即连续x^y
必须看起来像......)
观察结果是
x^y looks like ???...?100...0 if and only if
x and y look like ???...?:10...0
| <-- remember? the 1 location !!
该|
位置可以通过x&-x
或找到y&-y
。(为什么?为什么必须-
使用 2 的补码机来完成?)
但是,:
必须检查位置以查看它是1
(为什么?) 并且???...?
是000...0
。(为什么?)
所以,
x^y looks like ???...?100...0 and
(y&-y)<<1 looks like 000...0100...0
这解释了x^y ^ ((y&-y)<<1)
测试。
-------------------------------------------------- -----------------
为什么会这样: ... 是此处使用的特定格雷码属性的结果。关于为什么这个格雷码应该具有这些属性的检查和解释太复杂了,无法在此给出。
-------------------------------------------------- --------------------
由于 OP 代码问题,以前的答案的不足之处的评论。
警告 1:为了明确起见,OP 问题中的算法:
private static int graycode(byte term1, byte term2) {
byte x = (byte)(term1^term2); // why use XOR?
int count = 0;
while(x!=0)
{
x = (byte)(x &(x-1)); // why use bitwise operator?
count++; // what is count?
}
return count == 1;
}
对连续格雷码有一个有趣的解释。当任何两个二进制序列在单个位位置不同时,它确实会正确报告。
如果通过连续代码意味着格雷码用于枚举单调排序,则存在问题。
具体来说,代码将为true
所有这些对返回:
000, 001 or 000, 010 or 000, 100
所以可能会订购,001, 000, 010
但接下来可以100
去哪里?该算法(正确地)报告100
与其中任何一个的“连续性”001 or 010
是false
。
因此在枚举中100
必须紧跟在前面或后面000
,但不能紧跟在 or 前面或001
后面010
。噢噢噢!!!
警告 2:注意将最低位 1 位x = (byte)(x & (x-1))
重置为零。x
参考:
格雷码增量函数
从第 (n-1) 个格雷码导出第 n 个格雷码
https://electronics.stackexchange.com/questions/26677/3bit-gray-counter-using-d-flip-flops-and-logic- gates
如何在恒定时间内找到格雷码中的下一位变化?
如何判断两个数字是否是格雷码序列中的连续数字