0

My class wraps an object of type Vector3D, which consists of three double typed fields x, y and z. I'd like to create a hash based on those values but since double is 64 bit and int only 32, I'd need to "break" each coordinate in half and impose the first half on the second.

If we pretend that our variable is 4 bit wide and the input is 8 bit wide, I'd like to do the following.

x = 10010101
y = 01010111
z = 11110010

x1 = 1001
x2 = 0101
y1 = 0101
y2 = 0111
z1 = 1111
z0 = 0010

So that the resulting hash of width 4 bits would be, e.g. XOR on the above. Not sure how to perform the appropriate bitwise operations on double so that it ends up in my int. Googling gave me only the docs and those didn't make me any wiser.

Still, I feel that this is a standard issue and that the solution should be easy to find, if using the right keywords. Any help?

Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
  • 3
    `double.GetHashCode()` ? – Ivan Stoev Sep 11 '16 at 16:24
  • @IvanStoev And then just go *x.GetHashCode()^y.GetHashCode()*? Good idea. What if I'd like to do as I describe in the question (e.g. for some computations that make sense in my hashing scenario)? – Konrad Viltersten Sep 11 '16 at 16:27
  • How are you dealing with equality? Remember equal vectors must have the same hash code. – InBetween Sep 11 '16 at 16:27
  • @InBetween I do compare the coordinates with each other under a certain epsilon approximation. So I I check whether those are equal-ish. – Konrad Viltersten Sep 11 '16 at 16:28
  • You can apply any hash combinator (function). The point is that you use your class members `GetHashCode` implementations to build your hash. The same ways as you will the use their equality comparison in your `Equals`. – Ivan Stoev Sep 11 '16 at 16:29
  • The epsilon approximation is problem though. – Ivan Stoev Sep 11 '16 at 16:31
  • 1
    Then there is no way to implement a compatible hash code. I learned it the hard way, see [this](http://stackoverflow.com/q/38590854/767890) question and my incorrect answer and discussion in comments. – InBetween Sep 11 '16 at 16:33
  • @InBetween I'd like to challenge that statement. What if the hash in my class corresponds to the distance from origo? That's what I'm using now and it works except that the *doubles* can get a bit too large. If I only can trim them down a bit, I'd be happy. Suggestions? – Konrad Viltersten Sep 11 '16 at 16:35
  • The distance is a double so your just punting forward the problem. Now you need to somehow implement an equalish distance and your back in square one. – InBetween Sep 11 '16 at 16:38
  • @InBetween I don't see it. Perhaps I explained it incorrectly. My idea is to get e.g. 2.34, 2.98, 2.70 and get them hash of 2 (an integer). Then, 3.13, 3.00, 3.98 will get hash of 3. Doing so, as long as my numbers don't exceed the maximum of int, I'm good. Then, **if** those numbers exceed the maximum, I can just wrap around treating 5.17 and 5.17+max_of_in as belonging to the same hash class of 5. What do I miss, please? – Konrad Viltersten Sep 11 '16 at 16:42
  • @KonradViltersten You can use `BitConverter.DoubleToInt64Bits` to get `Int64` values out of `doubles`, then get lower and higher `Int32` parts of each and proceed as in your example, but I don't think there will be any benefit of doing that. – Ivan Stoev Sep 11 '16 at 16:52
  • Because `double.GetHashCode` already does something like that - [reference source](http://referencesource.microsoft.com/#mscorlib/system/double.cs,01ee10483fa0a3ad) – Ivan Stoev Sep 11 '16 at 16:57
  • The problem is the following: two vectors that are equal *must* have the same distance to origin because they *must* have the same hashcode. So you somehow need to define a distance epsilon too so that equality of vectors corresponds to equality of distances to origin. Once you define an epsilon in distances you have the same hash problem. – InBetween Sep 11 '16 at 16:57
  • @InBetween With all respect for my brains being tired and slow, I claim that the problem you point out isn't a problem at all. Two vectors (let's play with 1D for smoothness) are equal, say 3.14 and 3.14. They have the same distance to the origin (3.14 to be precise) and the same hash (3 in this case). If they are not equal, say 3.14 and 3.15, they have different distances to the origin but still get into the same hash. I simply fail to see the problem (although I'm humble to suspect that it's due to my ignorance and your mistake, so please, feel free to shoot the argument I just made down). – Konrad Viltersten Sep 11 '16 at 18:02
  • 2
    Becuase vectors 2.999999999 and 3.00000001 are equal (difference is below your equality epsilon) and your distances will hash to 2 and 3 which is wrong. If you round when hashing instead of truncating then you'll have the problem with 2.499999999999 and 2.50000001. Dou you understand? – InBetween Sep 11 '16 at 18:16
  • Note, that simply hashing all bits will not match the definition of double.Equals. There's NaN for example. I think this has been a bug in the framework for double.GetHashCode() – usr Sep 11 '16 at 18:32
  • 2
    @InBetween Now that I see it, I understand the discussion you had in your faulty reply that you linked to. I want to express my gratitude for taking time to explain. I also want to point out that it's a dignified and honest action to share that with others instead of hiding the mistake. Hats off. – Konrad Viltersten Sep 11 '16 at 18:32
  • @usr So basically, the only option is to return a constant value for all hashes, like 1 or something, right? It seems so trivial and just wrong... Like we're throwing in the towel... – Konrad Viltersten Sep 11 '16 at 18:34
  • See this question: http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode/263416#263416 – pilotcam Sep 11 '16 at 18:41
  • double.GetHashCode totally works and your xor idea is the right approach (except that you need fuzzy matching which makes hash tables impossible to use). – usr Sep 11 '16 at 18:43
  • @Konrad Viltersten I see nothing wrong in making mistakes and learning from them and if it helps others then better yet. Thanks for the comment though, I appreciate it. – InBetween Sep 11 '16 at 19:21

0 Answers0