Каков подходящий алгоритм `GetHashCode ()` для двухмерной точечной структуры (предотвращение коллизий)

Рассмотрим следующий код:

struct Vec2 : IEquatable<Vec2>
{
    double X,Y;

    public bool Equals(Vec2 other)
    {
        return X.Equals(other.X) && Y.Equals(other.Y);
    }

    public override bool Equals(object obj)
    {
        if (obj is Vec2)
        {
            return Equals((Vec2)obj);
        }
        return false;
    }

    // this will return the same value when X, Y are swapped
    public override int GetHashCode()
    {
        return X.GetHashCode() ^ Y.GetHashCode();
    }

}

Помимо разговора о сравнении двойников на равенство (это всего лишь демонстрационный код), меня беспокоит то, что при замене значений X, Y происходит конфликт хешей. . Например:

Vec2 A = new Vec2() { X=1, Y=5 };
Vec2 B = new Vec2() { X=5, Y=1 };

bool test1 = A.Equals(B);  // returns false;
bool test2 = A.GetHashCode() == B.GetHashCode() // returns true !!!!!

, что должно нанести ущерб коллекции словарей. Итак, вопрос в том, как сформировать свойство из функции GetHashCode () для 2,3 или даже 4 значений с плавающей запятой, чтобы результаты не были симметричными и хэши не конфликтовали.

Редактировать 1:

Point реализует несоответствующее решение x ^ y , а PointF обертывает ValueType.GetHashCode () .

Rectangle имеет очень своеобразный (((X ^ ((Y << 13) | (Y >> 19))) ^ ((Ширина << 26) | (Ширина >> 6))) ^ ((Высота << 7) | (Высота >> 25))) выражение для хэш-кода , который, кажется, работает так, как ожидалось.

Редактировать 2:

'System.Double' имеет хорошую реализацию, поскольку он не считает каждый бит одинаково важным

public override unsafe int GetHashCode() //from System.Double
{
    double num = this;
    if (num == 0.0)
    {
        return 0;
    }
    long num2 = *((long*) &num);
    return (((int) num2) ^ ((int) (num2 >> 32)));
}
13
задан ja72 20 April 2013 в 18:32
поделиться