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