Сравните NSDecimalNumber с NSNumber получает неправильный результат - PullRequest
0 голосов
/ 28 мая 2018

Код прост, и вы можете воспроизвести его.

NSDecimalNumber *d1 = [NSDecimalNumber decimalNumberWithString:@"6560601600245628933"];
BOOL res = [d1 isEqualToNumber:@(6560601600245628934)];
NSLog(@"%@", @(res));

isEqualToNumber: всегда возвращает YES, даже если я сравниваю d1 с другими числами, такими как @6560601600245628930 ... Есть идеи?Это ошибка?

1 Ответ

0 голосов
/ 28 мая 2018

Анализ

NSDecimalNumber * compare: (который вызывается isEqualToNumber:) проверяет, является ли его аргумент (@(6560601600245628934) здесь) другим NSDecimalNumber, и еслиnot обращается к NSNumber compare: (NSNumber является суперклассом NSDecimalNumber).

Как NSNumber d1 сообщает свой тип как double - то есть CFNumberGetType() возвращает kCFNumberDoubleType - и с учетом double NSNumber s compare: сравнивает два значения как double.

Ваше первое значение (decimalNumberWithString:@"6560601600245628933") сохраняется без потерь в видеNSDecimalNumber, но имеет более значимые цифры, чем double, и преобразование теряет точность.

Ваше второе значение (@(6560601600245628934)) сохраняется NSNumber как 64-разрядное целое число (kCFNumberSInt64Type)) без потери точности, но при преобразовании в удвоение теряет точность.

С вариантами, которые вы опробовали, оба числа, представленные как double, одинаковы.

Обходной путь

Измените:

@(6560601600245628934)

на:

[NSDecimalNumber numberWithLongLong:6560601600245628934LL]

, чтобы создать значение NSDecimalNumber непосредственно из целого числа.Это приведет к тому, что оба аргумента isEqualToNumber: будут NSDecimalNumber, и при сравнении не будет потеряна точность.

Ошибка или функция?

Возможно, это классифицируетсякак документация ошибка в том, что я не нашел нигде задокументированного (что далеко не убедительно!), что сравнение будет сделано с double s.Отправьте сообщение об ошибке на bugreport.apple.com и посмотрите, что они говорят.

...