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..
_______________________________________________
Gnustep-dev mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/gnustep-dev