gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: isEqual: and hash in NSDate


From: Adrian Robert
Subject: Re: isEqual: and hash in NSDate
Date: Fri, 22 Jul 2005 10:57:03 -0400


On Jul 21, 2005, at 3:49 PM, Jeremy Bettis wrote:

I have a problem with the implementations of isEqual: and hash in NSDate.
 
Let's say we have two dates:
 
NSDate *a, *b;
// This is actually a common case if you are doing floating point math to generate dates and get small rounding errors.
a = [NSDate dateWithTimeIntervalSinceReferenceDate:100000.001];
b = [NSDate dateWithTimeIntervalSinceReferenceDate:99999.998];
 
printf("a = %d, b=%d, equal=%d\n", [a hash] , [b hash], [a isEqual:b]);
 
// this code will print a = 100000, b = 99999, equal = 1
 
This breaks the NSDictionary rule that hash of two objects must equal if they are -isEqual:.
 
I propose that we change the implementations to this:
- (unsigned) hash
{
  return (unsigned)([self timeIntervalSinceReferenceDate]+0.5);
}
- (BOOL) isEqual: (id)other
{
  if (other == nil)
    return NO;
  if ([other isKindOfClass: abstractClass]
    && (int)(otherTime(self)+0.5) == (int)(otherTime(other)+0.5) )
    return YES;
  return NO;
}
After my change the program's output changes to:
a = 100000, b = 100000, equal = 1
 
I realize that the dates 100.5 and 100.49 are now not -isEqual:, but you have to draw the line somewhere, and putting it at .000 as the old code was worse.

This really seems like a hack (not that it's any worse than the current state :). Couldn't the implementations of -hash and -isEqual be aligned without this loss of information? E.g. something like [warning, sloppy first-attempt code here]:

-isEqual:other
  return abs(selfVal - other->selfVal) < epsilon;

-hash
  return selfVal / epsilon;
(or maybe (selfVal + epsilon/2.0) / epsilon)

I think the problem with this is the division in -hash would need to be carried out at a higher precision than the floating point representation of selfVal uses. But maybe this could be worked around or lived with somehow? E.g., if we used 8-byte floating point, epsilon was 0.001 (1 msec) and we were willing to accept inaccuracy for dates beyond 100000 AD, would it work then? Unfortunately my numerical computation class was WAY too long ago..





reply via email to

[Prev in Thread] Current Thread [Next in Thread]