title: Implementing -hash and -isEqual for a geo coordinate class
body: <p>I have an object which stores a latitude/longitude/altitude, and need <strong>reliable</strong> and <strong>fast</strong> <code>-hash</code> and <code>isEqual</code> implementations. I am using <code>double</code> to store all of the primitives.</p>
  
  <p>The accepted answer for <a href="https://stackoverflow.com/questions/254281/best-practices-for-overriding-isequal-and-hash">Best practices for overriding isEqual: and hash</a>, looks good, but it only talks about <code>integer</code> values.</p>
  
  <p>My question is how to deal with doubles, since they aren't precise values. I want to compare the primitives within 8 decimal places, which is already quite a bit more accurate than the GPS chip itself.</p>
  
  <p>Here is what I've come up with so far, have I done it right or does it need improvement?</p>
  
  <p>My <code>-isEqual:</code> implementation is fairly simple:</p>
  
  <pre><code>- (BOOL)isEqualToAGPoint:(AGPoint *)otherPoint
  {
    if (fabs(otherPoint-&gt;latitude - latitude) &gt; 0.00000001)
      return NO;
  
    if (fabs(otherPoint-&gt;longitude - longitude) &gt; 0.00000001)
      return NO;
  
    if (fabs(otherPoint-&gt;altitude - altitude) &gt; 0.00000001)
      return NO;
  
    return YES;
  }
  </code></pre>
  
  <p>But I'm not so sure about my <code>-hash</code> implementation:</p>
  
  <pre><code>- (NSUInteger)hash
  {
    NSUInteger prime = 31;
    NSUInteger result = 1;
  
    result = prime * result + lround(latitude * 100000000);
    result = prime * result + lround(longitude * 100000000);
    result = prime * result + lround(altitude * 100000000);
  
    return result;
  }
  </code></pre>
  
  <p>A quick test demonstrates it seems to work as I need it to:</p>
  
  <pre><code>// all three have the same longitude and altitude, while a and b have slightly different (but should be considered identical) latitudes, while c's latitude is just different enough to be considered not equal to the a and b
  AGPoint *a = [[AGPoint alloc] initWithLatitude:-16.922608127 longitude:145.77124538 altitude:2.74930134];
  AGPoint *b = [[AGPoint alloc] initWithLatitude:-16.922608128 longitude:145.77124538 altitude:2.74930134];
  AGPoint *c = [[AGPoint alloc] initWithLatitude:-16.922608147 longitude:145.77124538 altitude:2.74930134];
  
  NSLog(@"a == b: %i", (int)[a isEqual:b]);
  NSLog(@"a == c: %i", (int)[a isEqual:c]);
  NSLog(@"hash for a: %lu  b: %lu c: %lu", (unsigned long)[a hash], (unsigned long)[b hash], (unsigned long)[c hash]);
  
  output:
    a == b: 1
    a == c: 0
    hash for a: 3952407433  b: 3952407433 c: 3952405511
  </code></pre>
  
  <p>Does this look correct?</p>