将NSDecimalNumber 与NSNumber进行比较得到错误的结果



代码很简单,你可以重现它。

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

isEqualToNumber:总是返回YES,即使我将d1与其他数字(如@6560601600245628930(进行比较......有什么想法吗?这是一个错误吗?

分析

NSDecimalNumbercompare:(由isEqualToNumber:调用(检查它的参数(@(6560601600245628934)这里(是另一个NSDecimalNumber,如果不是诉诸NSNumbercompare:(NSNumberNSDecimalNumber的超类(。

NSNumberd1将其类型报告为double– 即CFNumberGetType()返回kCFNumberDoubleType– 并且给定doubleNSNumbercompare:将两个值比较为double

你的第一个值(decimalNumberWithString:@"6560601600245628933"(作为NSDecimalNumber被存储起来,没有宝贵的损失,但比double有更多的有效数字,转换失去了精度。

你的第二个值(@(6560601600245628934)(由NSNumber存储为64位整数(kCFNumberSInt64Type(,没有精度损失,但当转换为双精度时会失去精度。

对于变体,您尝试过表示为double时的两个数字是相同的。

解决方法

改变:

@(6560601600245628934)

自:

[NSDecimalNumber numberWithLongLong:6560601600245628934LL]

以直接从整数创建NSDecimalNumber值。这将导致两个参数都NSDecimalNumberisEqualToNumber:,并且在进行比较时不会丢失精度。

错误或功能?

它可能被归类为文档错误,因为我没有在任何地方找到它的文档(这远非决定性的!(比较将与doubles进行比较。 在 bugreport.apple.com 提交错误报告,看看他们怎么说。

最新更新