NSJSONSerialization是否将数字反序列化为NSDecimalNumber? [英] Does NSJSONSerialization deserialize numbers as NSDecimalNumber?

查看:286
本文介绍了NSJSONSerialization是否将数字反序列化为NSDecimalNumber?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

采用以下代码:

NSError *error;
NSString *myJSONString = @"{ \"foo\" : 0.1}";
NSData *jsonData = [myJSONString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *results = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];

我的问题是,results[@"foo"]是NSDecimalNumber还是二进制或浮点数等有限二进制精度的东西?基本上,我的应用程序要求NSDecimalNumber附带的无损精度,并且需要确保JSON反序列化不会由于double/floats等而导致舍入.

My question is, is results[@"foo"] an NSDecimalNumber, or something with finite binary precision like a double or float? Basically, I have an application that requires the lossless accuracy that comes with an NSDecimalNumber, and need to ensure that the JSON deserialization doesn't result in rounding because of doubles/floats etcetera.

例如如果将其解释为浮点数,那么我会遇到这样的问题:

E.g. if it was interpreted as a float, I'd run into problems like this with precision:

float baz = 0.1;
NSLog(@"baz: %.20f", baz);
// prints baz: 0.10000000149011611938

我尝试将foo解释为NSDecimalNumber并打印结果:

I've tried interpreting foo as an NSDecimalNumber and printing the result:

NSDecimalNumber *fooAsDecimal = results[@"foo"];
NSLog(@"fooAsDecimal: %@", [fooAsDecimal stringValue]);
// prints fooAsDecimal: 0.1

但是后来我发现在NSDecimalNumber上调用stringValue并不会打印所有有效数字,例如...

But then I found that calling stringValue on an NSDecimalNumber doesn't print all significant digits anyway, e.g...

NSDecimalNumber *barDecimal = [NSDecimalNumber decimalNumberWithString:@"0.1000000000000000000000000000000000000000000011"];
NSLog(@"barDecimal: %@", barDecimal);
// prints barDecimal: 0.1

...因此打印fooAsDecimal不会告诉我results[@"foo"]是否在某些时候被JSON解析器四舍五入到了有限精度.

...so printing fooAsDecimal doesn't tell me whether results[@"foo"] was at some point rounded to finite precision by the JSON parser or not.

要清楚,我意识到我可以在JSON表示中使用字符串而不是数字来存储foo的值,即"0.1"而不是0.1,然后使用[NSDecimalNumber decimalNumberWithString:results[@"foo"]].但是,我感兴趣的是NSJSONSerialization类如何反序列化JSON数字,因此我知道这是否真的必要.

To be clear, I realise I could use a string rather than a number in the JSON representation to store the value of foo, i.e. "0.1" instead of 0.1, and then use [NSDecimalNumber decimalNumberWithString:results[@"foo"]]. But, what I'm interested in is how the NSJSONSerialization class deserializes JSON numbers, so I know whether this is really necessary or not.

推荐答案

NSJSONSerialization(在Swift中为JSONSerialization)遵循以下常规模式:

NSJSONSerialization (and JSONSerialization in Swift) follow the general pattern:

  1. 如果数字只有整数部分(无小数或指数),请尝试将其解析为long long.如果没有溢出,请返回带有long longNSNumber.
  2. 尝试使用strtod_l解析双精度型.如果没有溢出,请返回带有doubleNSNumber.
  3. 在所有其他情况下,请尝试使用NSDecimalNumber来支持更大范围的值,特别是尾数最多为38位,指数在-128 ... 127之间.
  1. If a number has only an integer part (no decimal or exponent), attempt to parse it as a long long. If that doesn't overflow, return an NSNumber with long long.
  2. Attempt to parse a double with strtod_l. If it doesn't overflow, return an NSNumber with double.
  3. In all other cases, attempt to use NSDecimalNumber which supports a much larger range of values, specifically a mantissa up to 38 digits and exponent between -128...127.

如果您查看其他人张贴的示例,您会看到,当值超出double的范围或精度时,您会得到NSDecimalNumber.

If you look at other examples people have posted you can see that when the value exceeds the range or precision of a double you get an NSDecimalNumber back.

这篇关于NSJSONSerialization是否将数字反序列化为NSDecimalNumber?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆