2011-04-30 37 views
2

我有下面的代码:我数学真的不好,我想要做一个二元运算

public void AddHash(int val) 
    { 
     m_Hash ^= (val & 0x3FFFFFF); 
     m_Hash ^= (val >> 26) & 0x3F; 
    } 

我很想知道它做什么的挫折感,但我会知道如何建立一个bool HasHash(int val),告诉我m_Hash是否有这个数字或不...

这样的事情?

public bool HasHash(int val) 
    { 
     return (m_Hash & val) == 0; 
    } 
+3

维基百科在按位运算上有一个很好的页面:http://en.wikipedia.org/wiki/Bitwise_operations。 – 2011-04-30 18:56:52

回答

3

编辑修复@schnaader发现的错误:它做了什么?此代码可能希望由6位旋转val向左(顺时针方向)形成的那些补总和(编辑:不是产品,因为我以前说的) - 异或 - 即旋转的值和当前值m_Hash,以产生新的m_Hash。新的m_Hash将在下次调用AddHash()时使用。

但是,写入的代码有一个错误:它只向左旋转val的高位6位,留下val的低位26位。然后将代码与xors合并为三个值:

  1. 新的低位(旧的高位)6位val;
  2. 原始的,未移位的低位26位的val;和
  3. m_Hash

的电流值而使结果m_Hash

它是如何做到的?您可以将其映射出来并进行仿真:

  1. val & 0x3FFFFFF表示提取val的低位26位。
  2. xorm_Hash

  3. 的电流值的那些26个比特现在转向val向右使得低阶26个比特脱落低位端,留下什么曾经是高位6位val的低位6位val

  4. 掩码0x3f只提取那些低阶6位(如果一些无关位移入val的高位部分)。
  5. xor那些当前值为m_Hash的低6位给出新的m_Hash

你知道旋转和排斥是计算散列的常用操作。

编辑: @schnaader指出原始代码中的错误:该代码忘记做旋转的另一条腿:将低位26位向左移6位。为了解决这个问题,代码应该读取是这样的:

public void AddHash(int val) 
{ 
    m_Hash ^= ((val & 0x3FFFFFF) << 6); 
    m_Hash ^= (val >> 26) & 0x3F; 
} 

至于你HasHash()功能:你应该知道,说

return (m_Hash & val) == 0;

将在许多情况下返回TRUE,包括一些ÿ你可能不想要。例如,如果m_Hash == 0xC0val == 0x03,该函数将返回TRUE。

+0

绝佳回答+1 – bevacqua 2011-05-01 15:44:57

3

的代码做什么

它采用的val最后26位,并使用XORm_Hash结合它。之后,它将val的前6位与此组合。所以一个32位长度的整数将被减少到26位。根据pigeonhole principle,这是而不是可逆。

HasHash功能

所以,你将无法建立,即使你只叫AddHash只有一次,因为在val多个输入值将导致相同m_hashHasHash功能。

+0

+1好收获!谢谢! – 2011-04-30 23:44:42

+0

好回答+1 – bevacqua 2011-05-01 15:45:16