1

“连续格雷码”应该是什么意思?我的意思是 10 和 11 在十进制系统中是连续的,但“格雷码连续”是什么意思?我只知道格雷码是一个二进制数字系统,其中两个连续的值只有一位不同。

这是在线解决方案,但我无法理解

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

4 回答 4

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 结果进行与运算,则每次结果都是 0。这是您的解决方案中实现的逻辑:对于连续的格雷码对,while 循环将只运行一次(和 increment count),之后它将终止,因为它x已变为 0。所以count = 1最后。对于非连续对,循环将运行不止一次(试一试),count最后会大于 1。

该函数以此为基础,如果count== 1 则返回 1,否则返回 0。有点晦涩,但它完成了工作。

于 2016-02-29T02:25:17.613 回答
1

这意味着这两个数字仅相差一位。

所以解决方案从对这两个数字进行异或运算开始。xor 运算结果为 1,其中操作数的位不同,否则为零。

因此,您需要计算 xor 结果中的位数并与 1 进行比较。这就是您下载的示例所做的。这种在二进制数中计数 1 的方法是由 Brian Kernighan 所熟知的一种方法。状态x = (byte)(x & (x-1))是位魔法,将最高位 1 位重置为零。还有很多其他的

或者,您可以使用 1 位搜索 8 个可能字节的表。

byte one_bit_bytes[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
于 2016-02-29T02:11:47.690 回答
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) 进行按位与运算。使用上面描述的算术属性,在每次迭代中,恰好有一个“1”数字从数字中消失(从右边开始,即最低有效位)。

通过计算迭代次数,我们可以知道数字 X 中最初存在多少个“1”位。当变量 X 等于 0 时,迭代停止。

其他人已经回答了关于格雷码的问题。我的回答只解释了“位计数”是如何工作的(在对两个值进行异或之后)。

于 2016-02-29T02:54:01.957 回答
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)); }

尤其是这个答案(最好的):
如何查找两个数字是否是格雷码序列中的连续数字

用 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,与 不同的位XOR1,否则位必须匹配且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。

还记得补码,~函数aka1^b吗?测试最后一位x^yXOR'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 010false

因此在枚举中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
如何在恒定时间内找到格雷码中的下一位变化?
如何判断两个数字是否是格雷码序列中的连续数字

于 2017-03-05T02:10:00.150 回答