采取以下代码:
NSError *error; NSString *myJSONString = @"{ \"foo\" : 0.1}"; NSData *jsonData = [myJSONString dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary *results = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
我的问题是,结果[@“foo”]是一个NSDecimalNumber,还是有限二进制精度的东西,如double或float?基本上,我有一个应用程序需要NSDecimalNumber带来的无损准确度,并且需要确保JSON反序列化不会导致四舍五入,因为双精度/浮点数等等.
例如.如果它被解释为一个浮点数,我会遇到这样的问题与精度:
float baz = 0.1; NSLog(@"baz: %.20f",baz); // prints baz: 0.10000000149011611938
我尝试将foo解释为NSDecimalNumber并打印结果:
NSDecimalNumber *fooAsDecimal = results[@"foo"]; NSLog(@"fooAsDecimal: %@",[fooAsDecimal stringValue]); // prints fooAsDecimal: 0.1
但是后来我发现在NSDecimalNumber上调用stringValue不会打印所有有效数字,例如…
NSDecimalNumber *barDecimal = [NSDecimalNumber decimalNumberWithString:@"0.1000000000000000000000000000000000000000000011"]; NSLog(@"barDecimal: %@",barDecimal); // prints barDecimal: 0.1
…所以打印fooAsDecimal不告诉我,结果[@“foo”]是否在某种程度上被JSON解析器四舍五入到有限的精度.
要清楚,我意识到我可以使用一个字符串而不是JSON表示中的数字来存储foo的值,即“0.1”而不是0.1,然后使用[NSDecimalNumber decimalNumberWithString:results [@“foo”]].但是,我感兴趣的是NSJSONSerialization类如何反序列化JSON数字,所以我知道这是否真的有必要.
解决方法
NSJSONSerialization(和Swift中的JSONSerialization)遵循一般模式:
>如果一个数字只有整数部分(无小数或指数),则尝试将其解析为长整数.如果没有溢出,返回一个很长的NSNumber.
>尝试用strtod_l解析一个double.如果没有溢出,返回一个NSNumber为双.
>在所有其他情况下,尝试使用支持更大范围值的NSDecimalNumber,特别是最多38位数的尾数和-128 … 127之间的指数.
如果你看看别人发布的其他例子,你可以看到,当值超过一个double的范围或精度时,你会得到一个NSDecimalNumber.