Анализ
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 и посмотрите, что они говорят.