什么是"连续的灰色代码"应该是什么意思?我的意思是10和11在十进制系统中是连续的,但在格雷码中连续是#34;"含义?我只知道格雷码是一个二进制数字系统,其中两个连续值只有一位不同。
这是一个在线解决方案,但我无法理解这个
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;
}
我试着理解花了一个小时,但我仍然没有线索。
答案 0 :(得分:5)
如果两个数字在二进制表示中仅相差一位,则它们在格雷码中被认为是连续的,例如111和101仅相差第二位。您检查的函数是否有两个输入字节只有一个位使它们不同。因此111和101将从函数返回1,而111和100将返回0。
XOR用于查找两个数字之间的差异;当比特不同时,XOR产生1,否则例如0。 1111 XOR 1011将给出0100.因此,对于XOR,每个位差异在该位置以1突出显示。如果两个数字都是连续的格雷码,那么在XOR的结果中应该只有一个1。不止一个1表示多个差异因此不符合标准。 XOR结果存储在变量x
中。
接下来的任务是计算1的数量 - 因此变量count
。如果你尝试其他灰色代码对(更长的位长),你会注意到获得的XOR值将始终采用这种格式(忽略前导零):10,100,1000等。基本上,1后跟零或者,换句话说,总是2的力量。
如果这些样本XOR结果减1,您将获得:01,011,0111等。如果这些新值与原始XOR结果进行AND运算,则每次都会得到0。这是您的解决方案中实现的逻辑:对于连续的灰色代码对,while循环只运行一次(并且递增count
),之后它将终止,因为x
已变为0.所以{{ 1}}在最后。对于非连续对,循环将运行多次(尝试)并且count = 1
最后将大于1。
如果count
== 1,则函数使用此作为返回1的基础,否则返回0。
有点模糊,但它完成了工作。
答案 1 :(得分:1)
这意味着两个数字恰好相差一位。
因此,解决方案始于xor'这两个数字。 xor运算产生1,其中操作数的位不同,否则为零。
因此,您需要计算xor结果中的位数并与1进行比较。这是您下载的示例所执行的操作。由于Brian Kernighan,这种以二进制数计数1的方法是一种相当熟知的方法。状态x = (byte)(x & (x-1))
有点魔力,将最高阶1位重置为零。 There are lots of others
或者,您可以使用1位搜索8个可能字节的表。
byte one_bit_bytes[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
答案 2 :(得分:1)
这是一种非直观的方法来计算二进制数中的多少位等于'1'。
它需要二进制算术知识。从减去1的十进制数开始会发生什么,该数字由'1'后跟一个或多个零写:你得到一个9的序列,其长度等于零的数量:
1000000 - 1 = 999999
类似的事情发生在二进制数字上。如果从非负二进制数中减去1,则所有最低的'0'数字都将替换为'1',而在这些零之前的'1'将替换为零。这是从借用二进制的方式得出的。例如:
0101_0000_0001_0000 - 1 = 0101_0000_0000_1111
aaaa aaaa aaab cccc -> aaaa aaaa aaab cccc
符号:强调提高易读性。字母a上方出现的所有数字都保持不变。字母b上方出现的数字“1”变为“0”。字母c上方出现的数字“0”变为“1”。
下一步包括使用两个数字(X)和(X-1)进行按位AND运算。利用上面描述的算术属性,在每次迭代中,只有一个'1'数字从数字中消失(从右边开始,即最低有效位)。
通过计算迭代次数,我们可以知道在数字X中最初存在多少“1”位。当变量X等于零时,迭代停止。
其他人已经回答了有关格雷码的问题。我的回答只解释了“位计数”是如何工作的(在对两个值进行异或后)。
答案 3 :(得分:0)
这是对特定格雷码单调排序(二进制反射格雷码)的天真测试:
// 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)); }
特别注意这个答案(最好):
How to find if two numbers are consecutive numbers in gray code sequence
用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。
还记得补语,~
函数又称1^b
吗?要使用x^y
测试最后一位XOR
为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
的位置也匹配。
更有趣的是,对于连续数字, next 更高阶的总是不同(对于此格雷码)位置位置!
所以,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
之前或之后,但不能紧接在001
或010
之前或之后。的 DOH !!! 强>
警告2:注意x = (byte)(x & (x-1))
将{{1>}的 最低 订单1位重置为零。
参考:
Gray code increment function
Deriving nth Gray code from the (n-1)th Gray Code
https://electronics.stackexchange.com/questions/26677/3bit-gray-counter-using-d-flip-flops-and-logic-gates
How do I find next bit to change in a Gray code in constant time?
How to find if two numbers are consecutive numbers in gray code sequence