What is an appropriate `GetHashCode()` algorithm for a 2D point struct (avoiding clashes)

前端 未结 5 2006
长发绾君心
长发绾君心 2020-12-20 11:31

Consider the following code:

struct Vec2 : IEquatable
{
    double X,Y;

    public bool Equals(Vec2 other)
    {
        return X.Equals(other.X         


        
相关标签:
5条回答
  • 2020-12-20 12:06

    The hash codes approach works for interger coordinates but is not recommended for floating point values. With floating point coordinates one can create a point-set/pool by using a sorted sequence structure.

    A sorted sequence is a leaf version balanced binary tree.

    Here the keys would be the point coordinates.

    0 讨论(0)
  • 2020-12-20 12:13

    If size of your hash code is lesser than size of your struct, then clashes are inevitable anyways.

    0 讨论(0)
  • 2020-12-20 12:14

    Jon skeet has this covered:

    What is the best algorithm for an overridden System.Object.GetHashCode?

       public override int GetHashCode()
       {
           unchecked // Overflow is fine, just wrap
           {
               int hash = 17;
               // Suitable nullity checks etc, of course :)
               hash = hash * 23 + X.GetHashCode();
               hash = hash * 23 + Y.GetHashCode();
               return hash;
           }
       }
    

    Also, change your Equals(object) implementation to:

    return Equals(obj as FVector2);
    

    Note however that this could perceive a derived type to be equal. If you don't want that, you'd have to compare the runtime type other.GetType() with typeof(FVector2) (and don't forget nullity checks) Thanks for pointing out it's a struct, LukH

    Resharper has nice code generation for equality and hash code, so if you have resharper you can let it do its thing

    0 讨论(0)
  • 2020-12-20 12:19

    Hash collisions don't wreak havoc in a dictionary collection. They'll reduce the efficiency if you're unlucky enough to get them, but dictionaries have to cope with them.

    Collisions should be rare if at all possible, but they're don't mean the implementation is incorrect. XORs are often bad for the reasons you've given (high collisions) - ohadsc has posted a sample I gave before for an alternative, which should be fine.

    Note that it would be impossible to implement Vec2 with no collisions - there are only 232 possible return values from GetHashCode, but there are rather more possible X and Y values, even after you've removed NaN and infinite values...

    Eric Lippert has a recent blog post on GetHashCode which you may find useful.

    0 讨论(0)
  • 2020-12-20 12:23

    What are reasonable bounds for the coordinates?

    Unless it can be all possible integer values you could simply:

    const SOME_LARGE_NUMBER=100000; return SOME_LARGE_NUMBER * x + y;

    0 讨论(0)
提交回复
热议问题