Как обрабатывать числа с плавающей запятой и двойники при реализации -hash в target-c - PullRequest
11 голосов
/ 04 марта 2011

Я новичок в Objective-C, и я ищу лучший способ обработки примитивных операций с плавающей запятой и удвоения при реализации метода -hash в классе Objective-C. В этом вопросе я нашел несколько полезных советов по isEqual и по хешу в целом:

Лучшие практики для переопределения isEqual: и хеша

но ничего не говорится о том, как бороться с плавающими и удваивающими.

Моя лучшая попытка:

...
long lat = [[NSNumber numberWithDouble:self.latitude] longValue];
result = prime * result + (int) (lat ^ (lat >>> 32));
...

но я не уверен, что это правильный путь. Есть идеи?

Ответы [ 2 ]

12 голосов
/ 04 марта 2011

Если предположить, что реализация Apple -hash является адекватной, что не так с

result = [[NSNumber numberWithDouble: [self latitude]] hash];

или с использованием современного синтаксиса

result = [@([self latitude]) hash];
7 голосов
/ 18 октября 2014

Советы @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 с комментариями:

/* 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's 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 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...