Qu'est ce qu'un " appropriée GetHashCode()` algorithme pour un 2D point struct (en évitant les affrontements)

Considérons le code suivant:

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

}

Au-delà de la conversation de la comparaison de double pour l'égalité (c'est juste le code de démonstration), ce que je crains, c'est que il y a une table de hachage choc lorsque les valeurs X, Y sont échangés. Par exemple:

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

qui devrait semer le chaos dans un dictionnaire de la collection. Donc, la question est de savoir comment bien la forme de la GetHashCode() fonction pour 2, 3 ou même 4 valeurs à virgule flottante à ce que les résultats ne sont pas symétriques et les hachages de ne pas clash.

Edit 1:

Point met en œuvre inappropriée x ^ y solution, et PointF enveloppements ValueType.GetHashCode().

Rectangle a très particulière (((X ^ ((Y << 13) | (Y >> 19))) ^ ((Width << 26) | (Width >> 6))) ^ ((Height << 7) | (Height >> 25))) expression pour le code de hachage, qui semble fonctionner comme prévu.

Edit 2:

'Système.Double' a une jolie mise en œuvre, car il ne considère pas chaque bit aussi important

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)));
}
  • C'est bien de viser à minimiser les collisions, mais votre code doit attendre d'eux; ils seront toujours arriver
  • Hachages en découdront - int a une petite plage de valeurs possibles que double, et c'est encore plus petit comparativement à doublexdouble. Aussi, vous pourriez envisager un looser comparaison d'égalité - en raison de l'arrondissement, à deux les valeurs flottantes peuvent être très proches l'un de l'autre (ce que toute personne faisant une comparaison "à l'œil" permettrait de considérer l'égalité), mais encore de ne pas être exactement égal.
  • Ce n'est pas juste que (A,B) entre en collision avec (B,A). Grâce au fait que X^X --> 0 (C,C) entre en collision avec l'ensemble (D,D), et qui est beaucoup plus grand espace de collisions.
  • double possible de Créer un hashcode de deux nombres
InformationsquelleAutor ja72 | 2011-03-07