Ответ 1
В предположении, что реализация Apple -hash
является адекватной, что не так с
result = [[NSNumber numberWithDouble: [self latitude]] hash];
Или используя современный синтаксис
result = [@([self latitude]) hash];
Я новичок в Objective-C, и я ищу лучший способ обработки примитивных float и double при реализации метода -hash в классе Objective-C. Я нашел хороший совет по isEqual и хэш вообще в этом вопросе:
Рекомендации по переопределению isEqual: и хэш
но он ничего не говорит о том, как бороться с поплавками и удваивается.
Моя лучшая попытка:
...
long lat = [[NSNumber numberWithDouble:self.latitude] longValue];
result = prime * result + (int) (lat ^ (lat >>> 32));
...
но я не уверен, что это правильный путь. Любые идеи?
В предположении, что реализация Apple -hash
является адекватной, что не так с
result = [[NSNumber numberWithDouble: [self latitude]] hash];
Или используя современный синтаксис
result = [@([self latitude]) hash];
Советы @JeremyP об использовании NSNumber
были довольно хорошими, но я последовал этому более подробно. Поскольку CoreFoundation является открытым исходным кодом, я нашел, как CFNumber
реализует хеширующую функцию, и вот что я нашел:
Разделить число на интегральную и дробную часть, хэш обе части и суммировать их. Интегральная часть хэшируется по модулю и хеш-фактору, часть дроби хэшируется только умножением.
NSUInteger HashDouble(double value) {
double absolute = ABS(value);
double integral = round(absolute);
double fragment = absolute - integral;
NSUInteger integralHash = 2654435761U * fmod(integral, NSUIntegerMax);
NSUInteger fragmentHash = fragment * NSUIntegerMax;
return integralHash + fragmentHash;
}
Исходный код из комментариев CoreFoundation wth:
/* For use by NSNumber and CFNumber.
Hashing algorithm for CFNumber:
M = Max CFHashCode (assumed to be unsigned)
For positive integral values: (N * HASHFACTOR) mod M
For negative integral values: ((-N) * HASHFACTOR) mod M
For floating point numbers that are not integral: hash(integral part) + hash(float part * M)
HASHFACTOR is 2654435761, from Knuth multiplicative method
*/
#define HASHFACTOR 2654435761U
CF_INLINE CFHashCode _CFHashInt(long i) {
return ((i > 0) ? (CFHashCode)(i) : (CFHashCode)(-i)) * HASHFACTOR;
}
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));
}
Из файла ForFoundationOnly.h на opensource.apple.com.