如果给出两个十六进制数字,则查找它们是否可以在格雷码中连续

时间:2016-02-29 01:39:30

标签: java xor bitwise-xor gray-code

什么是"连续的灰色代码"应该是什么意思?我的意思是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;  
}  

我试着理解花了一个小时,但我仍然没有线索。

4 个答案:

答案 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不同,否则位必须匹配,XOR0

     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
当格雷码的任何的连续数字的最低位(xy)不同时,其余必须为相同!这是格雷码的定义。这意味着x^y 必须看起来像0000 ... 0001。

还记得补语,~函数又称1^b吗?要使用x^y测试最后一位XOR1

这解释了x^y ^ 1 -------------------------------------------

案例2
连续格雷码xy中的不同位的位置不是最低位。仔细查看这些格雷码连续数字。

 001       010       101     lower order bits all match
 011       110       111
   |        |          | <-- | mark location of lowest 1 
 010       100       010  <-- XOR's 

有趣的是,在格雷码中,当最低位在xy中匹配时,最低位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可以去哪里? 该算法(正确地)报告100001 or 010之间的“连续性”为false

因此,100必须紧接在枚举中000之前或之后,但不能紧接在001010之前或之后。的 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