Was ist ein angemessenes `GetHashCode ()` - Algorithmus für ein 2D point struct (Vermeidung von Zusammenstößen)

Betrachten Sie den folgenden code:

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

}

Jenseits der Unterhaltung zu vergleichen, verdoppelt sich für die Gleichstellung (das ist nur demo-code), was ich befürchte, ist, dass ein hash-clash, wenn X, Y Werte werden vertauscht. Zum Beispiel:

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 !!!!!

sollte Wrack Chaos in der dictionary-Auflistung. Die Frage ist also, wie man Eigentum bilden die GetHashCode() - Funktion für 2, 3 oder sogar 4 floating-point-Werte so, dass die Ergebnisse sind nicht symmetrisch und die hashes nicht zur Deckung zu bringen.

Edit 1:

Point implementiert die unangemessene x ^ y Lösung, und PointF wraps ValueType.GetHashCode().

Rectangle hat einen sehr eigenartigen (((X ^ ((Y << 13) | (Y >> 19))) ^ ((Width << 26) | (Width >> 6))) ^ ((Height << 7) | (Height >> 25))) Ausdruck für die hash-code, die scheint, wie erwartet.

Edit 2:

'- System.Double' hat eine schöne Umsetzung, wie er betrachtet nicht jedes bit ebenso wichtig

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)));
}
Es ist gut zu Zielen, um minimieren Kollisionen, aber dein code muss erwarten; Sie werden immer wieder passieren
Hashes wird clash - int hat einen kleineren Bereich der möglichen Werte als double, und es ist sogar noch kleiner, wenn im Vergleich zu doublexdouble. Auch, möchten Sie vielleicht zu prüfen, ein loser, der Geschlechter-Vergleich - bedingt durch die Rundung, zwei float-Werte können sehr nahe beieinander (was jemand tut, ein Vergleich "mit dem Auge" betrachten würden gleich), aber doch nicht genau gleich sein.
Es ist nicht nur, dass (A,B) kollidiert mit (B,A). Dank der Tatsache, dass X^X --> 0 es werden alle (C,C) kollidiert mit all (D,D), und das ist ein viel größerer Raum von Kollisionen.
mögliche Duplikate von Erstellen Sie ein hashcode von zwei zahlen

InformationsquelleAutor ja72 | 2011-03-07

Schreibe einen Kommentar