gnustep-dev
[Top][All Lists]

## 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..
```

```