Reputation: 90475
I'm implementing a custom GetHashCode for the System.Drawing.Point class in C#. My method currently fails the following requirement:
var hashA = MyGetHashCode(new Point(1, 0));
var hashB = MyGetHashCode(new Point(0, 1));
var hashC = MyGetHashCode(new Point(0, 0));
var hashD = MyGetHashCode(new Point(1, 1));
Assert.AreNotEqual(hashA ^ hashB, hashC ^ hashD);
To pass this test I'm sure that using new SHA256Managed().ComputeHash(currentHash) will do. But there is any other faster hashing algorithm? I know SHA256 is all about security, and I don't need that.
Upvotes: 3
Views: 5705
Reputation: 25834
If you know in advance that your point value is between 0 and N, you can use hashcode = X+Y*N;
This is a rather obvious possible hash. It's not random at all, has ugly repetition, and is generally pretty silly. It's equivalent to concatenating the bits of your two points, assuming N is a power of 2. And it's got perfect uniform distribution and no collisions.
I've used this strategy to excellent effect in the past, but admit it has some real (but obvious) limitations. The biggest one being what happens when N is large enough that N^2 won't fit into your hash value (i.e. painful collisions.
Upvotes: 0
Reputation: 3862
I don't know what your application is, but you may be looking for Zobrist hashing.
http://en.wikipedia.org/wiki/Zobrist_hashing
It can be updated incrementally, which makes it very fast.
Upvotes: 0
Reputation: 1062780
A simple hash? how about something like:
(17 * point.X) + (23 * point.Y);
Or for more obvious entropy:
int hash = -1047578147;
hash = (hash * -1521134295) + point.X;
hash = (hash * -1521134295) + point.Y;
(numbers from C#'s anonymous type code)
Upvotes: 6
Reputation: 52123
A simple Elf hash implementation (it's in delphi, shoudl be easy to translate)
function ElfHash(id : string; tableSize : integer) : integer;
var
i : integer;
h,x : longint;
begin
h := 0;
// Obtener el valor numérico
for i := 1 to Length(id) do
begin
h := (h shl 4) + Ord(id[i]);
x := h and $F0000000;
if x <;>; 0 then
h = h xor (x shr 24) xor x;
end;
// Ajustar al tamaño de la tabla
result := h mod tableSize;
end;
Upvotes: 1
Reputation: 12816
Here's an interesting article about hashing speed:
A Hash Function for Hash Table Lookup
Upvotes: 1
Reputation: 71945
Why are you doing this? Surely System.Drawing.Point
has a fine hashing function already?
You understand that test doesn't represent a strict requirement, right? Hash codes don't have to be unique.
If you really want a really good hash of the coordinates in question, you might want to start at this page about hashing multiple integers.
Upvotes: 3
Reputation: 47749
I know this isn't going to answer your question, but I must mention for the sake of other readers that you are changing the default behavior of a built in method of the framework. As per the documentation:
http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx
The default implementation of the GetHashCode method does not guarantee unique return values for different objects. Furthermore, the .NET Framework does not guarantee the default implementation of the GetHashCode method, and the value it returns will be the same between different versions of the .NET Framework. Consequently, the default implementation of this method must not be used as a unique object identifier for hashing purposes.
Upvotes: 1