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

时间:2018-05-28 13:28:49

标签: ios objective-c nsnumber nsdecimalnumber

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

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

isEqualToNumber:始终返回YES,即使我将d1@6560601600245628930等其他数字进行比较......任何想法?这是一个错误吗?

1 个答案:

答案 0 :(得分:2)

<强>分析

NSDecimalNumber&#39; s compare:(由isEqualToNumber:调用)检查其参数(@(6560601600245628934)此处)是另一个NSDecimalNumber,如果不是NSNumber的{​​{1}} compare:NSNumber的超级班级。

NSDecimalNumber NSNumber将其类型报告为d1时,double会返回CFNumberGetType() - 并且kCFNumberDoubleType {{1 {}} double将这两个值比较为NSNumber

您的第一个值(compare:)以double的形式存储而没有重大损失,但其有效位数高于decimalNumberWithString:@"6560601600245628933"且转换失去精确度。

您的第二个值(NSDecimalNumber)由double存储为64位整数(@(6560601600245628934))而没有精度损失,但转换为双精度丢失时。

根据这些变化,您在NSNumber表示的时候尝试过这两个数字是相同的。

解决方法

变化:

kCFNumberSInt64Type

为:

double

直接从整数创建@(6560601600245628934) 值。这将导致[NSDecimalNumber numberWithLongLong:6560601600245628934LL] 的两个参数都为NSDecimalNumber,并且在进行比较时不会丢失任何精度。

错误或功能?

它可能被归类为文档错误,因为我没有发现它在任何地方都有记录(这远非结论性!),将与isEqualToNumber:进行比较秒。在bugreport.apple.com提交错误报告,看看他们说了什么。