代码很简单,你可以重现它。
NSDecimalNumber *d1 = [NSDecimalNumber decimalNumberWithString:@"6560601600245628933"];
BOOL res = [d1 isEqualToNumber:@(6560601600245628934)];
NSLog(@"%@", @(res));
isEqualToNumber:
总是返回YES
,即使我将d1
与其他数字(如@6560601600245628930
(进行比较......有什么想法吗?这是一个错误吗?
分析
NSDecimalNumber
的compare:
(由isEqualToNumber:
调用(检查它的参数(@(6560601600245628934)
这里(是另一个NSDecimalNumber
,如果不是诉诸NSNumber
的compare:
(NSNumber
是NSDecimalNumber
的超类(。
当NSNumber
d1
将其类型报告为double
– 即CFNumberGetType()
返回kCFNumberDoubleType
– 并且给定double
NSNumber
的compare:
将两个值比较为double
。
你的第一个值(decimalNumberWithString:@"6560601600245628933"
(作为NSDecimalNumber
被存储起来,没有宝贵的损失,但比double
有更多的有效数字,转换失去了精度。
你的第二个值(@(6560601600245628934)
(由NSNumber
存储为64位整数(kCFNumberSInt64Type
(,没有精度损失,但当转换为双精度时会失去精度。
对于变体,您尝试过表示为double
时的两个数字是相同的。
解决方法
改变:
@(6560601600245628934)
自:
[NSDecimalNumber numberWithLongLong:6560601600245628934LL]
以直接从整数创建NSDecimalNumber
值。这将导致两个参数都NSDecimalNumber
isEqualToNumber:
,并且在进行比较时不会丢失精度。
错误或功能?
它可能被归类为文档错误,因为我没有在任何地方找到它的文档(这远非决定性的!(比较将与double
s进行比较。 在 bugreport.apple.com 提交错误报告,看看他们怎么说。