1

I'm overwriting the GetHashCode() Function for my Vector class. Its just contaning 3 floats X, Y, Z. I'm wondering whats the best way to do so.

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

I need this to quickly find a Vector in a big-Collection.

I don't want to just return X.GetHashCode() or so, because this would lead to too many equals checks for straight lines.

The problem with my current implementation is that, if the floats are really big I might get an integer overflow.

  • Is there a way to tell my compiler to just cut out any overflow?

  • Is there a better Solution?

Thanks in advance.

2
  • You could use the unchecked keyword, and then combine the values. See this question. Commented May 24, 2019 at 7:55
  • @Neijwiert seems good to me feel free to write an answer :) Commented May 24, 2019 at 8:00

2 Answers 2

5

Is there a way to tell my compiler to just cut out any overflow?

Yes, you can use the unchecked keyword for that. As @kalimag pointed out, only integral values throw exceptions on overflow.

Is there a better Solution?

The proper way to combine hash values would be:

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

See this question for explanation.

Sign up to request clarification or add additional context in comments.

2 Comments

float and double never throw overflow exceptions, they turn into negative or positive infinity. checked/unchecked only affects primitive integer types. Calling GetHashCode() on each individual float is probably still a good idea though to improve the quality of the combined hash code.
@kalimag you're right. But in this case the floats are converted to integral values and then do need to be unchecked for overflow. I edited the question to reflect your comment.
2

Often, when we combine hash codes manually, we do it with xor:

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

See Why is XOR the default way to combine hashes? for details

xor never throws any exception. You can let .Net to combine for you:

public override int GetHashCode() => HashCode.Combine(X, Y, Z);

4 Comments

How is it a better solution when pairs with the same value get 0 hashcode? suppose we have x,y,z = 2 and x,y,z = 3. Both get hashcode 0.
@Neijwiert: if x.GetHashCode() == 0 and y.GetHashCode() == 0 but z.GetHashCode() == 2 or 3 we have 0 ^ 0 ^ 2 == 2 and 0 ^ 0 ^ 3 == 3, you've probably mixed ^ and &
@Neijwiert actually they would not. if x,y,z = 2 x^y=0 but x^y^z=2 again.It' a slim solution thats why i prefer it. Every solution will have overlap since we put 96 bits of data in 32 bits. I have no time to determ right now wich will perform better
You're right, I forgot that after the first 2 it already turns to 0. It would however be a problem in case of a 2D vector though or anything with 2 fields.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.