Как справиться с переполнением в GetHashCode () - PullRequest
1 голос
/ 24 мая 2019

Я перезаписываю функцию GetHashCode() для моего класса Vector.Это всего лишь 3 поплавка X, Y, Z.Мне интересно, как лучше это сделать.

public override int GetHashCode()
{
    var sum = X + 3 * Y + 5 * Z;
    return sum.GetHashCode();
}

Мне нужно это, чтобы быстро найти Вектор в большой коллекции.

Я не хочу просто возвращаться X.GetHashCode() или около того, потому что это привело бы к слишком большому количеству проверок равенства для прямых линий.

Проблема с моей текущей реализацией состоит в том, что, если числа с плавающей точкой действительно большие, я могу получить целочисленное переполнение .

  • Есть ли способ сказать моему компилятору просто исключить переполнение?

  • Есть ли лучшее решение?

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 24 мая 2019

Есть ли способ сказать моему компилятору просто исключить переполнение?

Да, вы можете использовать для этого ключевое слово unchecked . Как указал @kalimag, только целочисленные значения генерируют исключения при переполнении.

Есть ли лучшее решение?

Правильный способ объединения значений хеш-функции:

public override int GetHashCode()
{
    unchecked
    {
        int hash = 17;
        hash = hash * 23 + X.GetHashCode();
        hash = hash * 23 + Y.GetHashCode();
        hash = hash * 23 + Z.GetHashCode();

        return hash;
    }
}

См. этот вопрос для объяснения.

1 голос
/ 24 мая 2019

Часто мы объединяем хеш-коды с xor (лучшее решение):

public override int GetHashCode() =>
  X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode();

См. Почему XOR является стандартным способом объединения хэшей? для получения подробной информации

xor никогда не вызывает исключений

...