How can we reinterpret a double or float as NSUInteger to create hash?
-
13-07-2021 - |
Question
This is my isEqual and hash custom operator
- (BOOL)isEqual:(id)object;
{
BGSearchParameter * theOther = (BGSearchParameter *)object;
BOOL isTheOtherEqual;
isTheOtherEqual = isTheOtherEqual && [self.Location isEqual:theOther.Location];
isTheOtherEqual = isTheOtherEqual && [self.keyword isEqual:theOther.keyword];
isTheOtherEqual = isTheOtherEqual && (self.Distance == theOther.Distance);
isTheOtherEqual = isTheOtherEqual && (self.SortByWhat == theOther.SortByWhat);
isTheOtherEqual = isTheOtherEqual && (self.startFrom == theOther.startFrom);
isTheOtherEqual = isTheOtherEqual && (self.numberOfIDstoGrab == theOther.numberOfIDstoGrab);
return isTheOtherEqual;
}
- (NSUInteger)hash
{
NSUInteger returnValue=0;
returnValue ^= self.Location.hash;
returnValue ^= self.keyword.hash;
return returnValue;
}
That one does the job. However, say I want to incorporate the distance and the startfrom into the hash.
I guess I will simply add:
returnValue ^= self.Distance;
It's an error because it's not compatible.
So what should I do instead?
Solution
I ended up turning the number into NSNumber and got the hash:
returnValue ^= @(self.Distance).hash;
returnValue ^= @(self.SortByWhat).hash;
returnValue ^= @(self.startFrom).hash;
returnValue ^= @(self.numberOfIDstoGrab).hash;
Martin answer is good. However, the result should be the same anyway and I don't want to implement another complicated function.
OTHER TIPS
This is what CFNumber
/NSNumber
use as hash value for float
and double
values, see for example ForFoundationOnly.h in Mac OS X 10.7.5 Source.
#define HASHFACTOR 2654435761U
CF_INLINE CFHashCode _CFHashDouble(double d) {
double dInt;
if (d < 0) d = -d;
dInt = floor(d+0.5);
CFHashCode integralHash = HASHFACTOR * (CFHashCode)fmod(dInt, (double)ULONG_MAX);
return (CFHashCode)(integralHash + (CFHashCode)((d - dInt) * ULONG_MAX));
}
CFHashCode
is defined as
typedef unsigned long CFHashCode;
Try this:
static NSUInteger doubleHash(float value) {
return *(NSUInteger *)&value;//gets bits
}
Notice the conversion to float. It decreases precision, but sizeof(float)==sizeof(NSUInteger).
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow