NSDecimalNumber持久化精度溢出的坑(╥﹏╥)

最近遇到了一个问题,将一个NSNumber对象存入NSUserDefaults,取出来的数值和存入前的数值竟然不一致。

比如存入的数值为6350939786827530754,但取出的数值变成了6350939786827531264

这个数并没有超过```long long


但为什么将一个```NSNumber```存入```NSUserDefaults```再取出来之后,会发生精度溢出呢?(恐慌脸)查看了一下,存入```NSUserDetaults```的那个```NSNumber```对象,实际是一个```NSDecimalNumber```对象,即```NSNumber```的一个子类。在调用系统的JSON解析库时,数值较大的数会被解析为一个```NSDecimalNumber```对象。

和```NSNumber```不同的是,```NSDecimalNumber```的```objCType```属性,返回的永远是```d```,即double,[官方文档](https://developer.apple.com/reference/foundation/nsdecimalnumber/1409042-objctype)中有这样的说明:
> For a decimal number object, this property always contains “d” (for double).

而在存入```NSUserDefaults```中时,```NSDecimalNumber```的```objCType```方法会被调用,```NSUserDefaults```应该会通过判断```objCType```来决定如何将数据持久化到硬盘。由于```NSDecimalNumber```的```objCType```永远为d,所以在持久化时,它将以double的形式被持久化,导致了精度溢出。
![](http://upload-images.jianshu.io/upload_images/164542-06ace4e7c3a3a644.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

不仅仅是存入```NSUserDefaults```中,在存入sqlite和存入Core Data时,```NSDecimalNumber```都有可能遇到精度溢出的问题(真坑)。

解决方法可能有这么几种:
1.在持久化之前,将```NSDecimalNumber```对象转化为```NSNumber```对象;
2.在持久化之前,将```NSDecimalNumber```归档为```NSData```,取出后unarchive回去
3.更简单粗暴的方法:持久化之前将```NSDecimalNumber```转化成```NSString```,取出时将```NSString```再转回数值

你可能感兴趣的:(NSDecimalNumber持久化精度溢出的坑(╥﹏╥))