NSDecimalNumber和大型无符号长整数(64位)整数

时间:2011-07-15 16:49:34

标签: objective-c cocoa

我正在处理来自JSON源的大型64位无符号整数,这些整数被解析为NSDecimalNumbers,这显然是“忠实地表示任意精度数字”。

我遇到的问题是我无法从本课程中获得正确的数字。例如(使用可能的最大值):

print (unsigned long long) [[NSDecimalNumber decimalNumberWithString:@"18446744073709551615"] unsignedLongLongValue]
= 0 // Incorrect
print (unsigned long long) [[NSDecimalNumber decimalNumberWithString:@"9223372036854775808"] unsignedLongLongValue]
= 9223372036854775808 // Correct
print (unsigned long long) [[NSDecimalNumber decimalNumberWithString:@"9223372036854775810"] unsignedLongLongValue]
= 9223372036854775808 // Incorrect

看起来我无法获得大于NSDecimalNumber中最大签名long long值的任何值。它不喜欢大于9223372036854775808的值。但是,似乎该数字以NSDecimalNumber中的完整精度存储,如:

po [[NSDecimalNumber decimalNumberWithString:@"18446744073709551615"] stringValue]
= 18446744073709551615

我注意到NSNumber对象可以处理这些大数字,而unsignedLongLongValue可以正常工作。它只是NSDecimalNumbers(我坚持使用),它们无效。

如何从NSDecimalNumbers中获取正确的无符号long long值?或者至少将它们转换为NSNumber对象,其中unsignedLongLongValue可以正常工作。

2 个答案:

答案 0 :(得分:11)

我通过开发者论坛得到了Apple对此问题的回复:

  

这是NSDecimalNumber的常见问题所在   访问器(例如[unsigned] longLongValue)通过doubleValue   accessor - 这个任何需要超过53位精度的值   将不恰当地四舍五入。随时报告一个关于此的Bug   问题并提到错误号8220543。

     

那就是说,如果你是公正的话   从JSON获取64位数字,你应该可以使用   NSNumber而不是NSDecimalNumber。

所以我通过将解析器从SBJson更改为JSONKit来解决它,这不仅快得多,而且还将数字映射到NSNumber对象而不是NSDecimalNumber对象。

答案 1 :(得分:6)

如果您仍想从NSDecimalNumber中提取无符号long long值,可以使用johne here建议的方法,并执行以下操作:

NSDecimalNumber *testNumber = [NSDecimalNumber decimalNumberWithString:@"18446744073709551615"];
unsigned long long ullvalue = strtoull([[testNumber stringValue] UTF8String], NULL, 0);
NSLog(@"Number:%llu", ullvalue);

产生

的正确结果
  

编号:18446744073709551615

我尝试使用NSScanner执行此操作:

NSScanner *theScanner = [[NSScanner alloc] initWithString:[testNumber stringValue]];
unsigned long long outputValue;

[theScanner scanLongLong:(long long *)&outputValue];
[theScanner release];

但不幸的是,它只读取带符号的long long值,因此上面给出了不正确的值9223372036854775807.。