【问题标题】:I'm really bad at math and I want to do a binary operation我数学真的很差,我想做一个二元运算
【发布时间】:2011-08-16 04:21:42
【问题描述】:

我有以下代码:

    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;
    }

【问题讨论】:

标签: c# binary-operators


【解决方案1】:

编辑以修复@schnaader 发现的错误: 它的作用是什么?此代码可能想要val 向左(顺时针)旋转 6 位并形成补码和 (编辑:不是产品,因为我' d 之前说过) -- 该旋转值与m_Hash 的当前值的异或,以产生一个新的m_Hash。下次调用 AddHash( ) 时将使用新的 m_Hash

但是,编写的代码有一个错误:它只将val 的高6 位向左旋转,而将val 的低26 位留在原处。然后代码将三个值异或在一起:

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

将结果留在m_Hash

它是如何做到的?你可以把它映射出来并模仿它:

  1. val & 0x3FFFFFF 表示提取val 的低26 位。
  2. xor当前值为m_Hash的那些26位

  3. 现在将val 向右移动,使得低位 26 位从低位端下降,将过去的 val 的高位 6 位留在低位 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 &amp; val) == 0;

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

【讨论】:

    【解决方案2】:

    代码的作用

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

    哈希函数

    因此,即使您只调用了一次AddHash,您也无法创建HasHash 函数,因为val 中的多个输入值将产生相同的m_hash 值。

    【讨论】:

      猜你喜欢
      • 2016-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-25
      相关资源
      最近更新 更多