Create a hashcode of two numbers

Viewed 33237

I am trying to create a quick hashcode function for a complex number class (a + b) in C#.

I have seen repeatedly the a.GetHashcode()^b.GetHashCode() method. But this will give the same hashcode for (a,b) and (b,a).

Are there any standard algorithm to do this and are there any functions in the .Net framework to help?

7 Answers

My normal way of creating a hashcode for an arbitrary set of hashable items:

int hash = 23;
hash = hash * 31 + item1Hash;
hash = hash * 31 + item2Hash;
hash = hash * 31 + item3Hash;
hash = hash * 31 + item4Hash;
hash = hash * 31 + item5Hash;
// etc

In your case item1Hash could just be a, and item2Hash could just be b.

The values of 23 and 31 are relatively unimportant, so long as they're primes (or at least coprime).

Obviously there will still be collisions, but you don't run into the normal nasty problems of:

hash(a, a) == hash(b, b)
hash(a, b) == hash(b, a)

If you know more about what the real values of a and b are likely to be you can probably do better, but this is a good initial implementation which is easy to remember and implement. Note that if there's any chance that you'll build the assembly with "check for arithmetic overflow/underflow" ticked, you should put it all in an unchecked block. (Overflow is fine for this algorithm.)

Here's a possible approach that takes into account order. (The second method is defined as an extension method.)

public int GetHashCode()
{
    return a.GetHashcode() ^ b.GetHashcode().RotateLeft(16);
}

public static uint RotateLeft(this uint value, int count)
{
    return (value << count) | (value >> (32 - count))
}

It would certainly be interesting to see how the Complex class of .NET 4.0 does it.

One standard way is this:

hashcode = 23
hashcode = (hashcode * 37) + v1
hashcode = (hashcode * 37) + v2

23 and 37 are coprime, but you can use other numbers as well.

What about this:

(a.GetHashcode() + b).GetHashcode()

Gives you a different code for (a,b) and (b,a) plus it's not really that fancy.

A stupid simple solution: This has worked for me in the past, but am not sure how GetHashCode() works.

return (a.ToString("0") + b.ToString("0")).GetHashCode();

In my case I wanted to implement an override of equals for custom class that was a member's first name and date of birth. I am pretty sure I could get away with not overriding GetHashCode, but I find the warning to be annoying. Here is my code (class: Member):

public override bool Equals(object obj)
    {
        Member that = (Member)obj;
        return this.memberFirstName == that.memberFirstName 
            && this.MemberDob.Date.ToString("yyyyMMdd") == that.MemberDob.Date.ToString("yyyyMMdd");
    }
    public override int GetHashCode()
    {
        return (this.memberFirstName + MemberDob.Date.ToString("yyyyMMdd")).GetHashCode();
    }
Related