Я очень плохо разбираюсь в математике и хочу сделать бинарную операцию - PullRequest
2 голосов
/ 30 апреля 2011

У меня есть следующий фрагмент кода:

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

Ответы [ 2 ]

3 голосов
/ 30 апреля 2011

РЕДАКТИРОВАТЬ, чтобы исправить ошибку, обнаруженную @schnaader: Что она делает?Этот код, вероятно, хочет, чтобы повернул val влево (по часовой стрелке) на 6 битов и сформировал сумму единиц дополнения (редактировать: не продукт, как я сказалдо) - xor - этого повернутого значения и текущего значения m_Hash, чтобы получить новое m_Hash.Этот новый m_Hash будет использоваться при следующем вызове AddHash( ).

Однако в написанном коде есть ошибка: он вращает только старшие 6 битов val влево, оставляя впоместите младшие 26 бит val.Затем код объединяет воедино три значения:

  1. новые 6 битов старшего разряда старшего разряда val;
  2. исходные 26 битов младшего разряда несмещенного значенияval
  3. текущее значение m_Hash

, оставляя результат в m_Hash.

Как это получается?Вы можете просто отобразить его и эмулировать:

  1. val & 0x3FFFFFF означает извлечение младших 26 битов val.
  2. xor те 26 битов с текущим значением m_Hash

  3. теперь смещены val вправо так, что младшие 26 битов уменьшаютсяот младшего конца, оставляя то, что раньше было старшими 6 битами val в младших 6 битах val.

  4. Маска с 0x3f для извлечениятолько те младшие 6 битов (в случае, если некоторые посторонние биты были сдвинуты в старшую часть val).
  5. xor эти младшие 6 битов с текущим значением m_Hash вдайте новый 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 при многих условияхitions, включая некоторые, которые вы, возможно, не хотите.Например, функция вернет TRUE, если m_Hash == 0xC0 и val == 0x03.

3 голосов
/ 30 апреля 2011

Что делает код

Он принимает последние 26 бит val и объединяет его с m_Hash, используя XOR . После этого он объединяет это с первыми 6 битами val. Таким образом, целое число с длиной 32 бита будет уменьшено до 26 бит. В соответствии с принципом голубиного отверстия , это не обратимо.

Функция HasHash

Таким образом, вы не сможете создать функцию HasHash, даже если вы вызывали AddHash только один раз, потому что несколько значений ввода в val приведут к одному и тому же значению m_hash.

...