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

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

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

这个数并没有超过long long的范围,从数值变化的形势(只有末尾几位发生了变化),可以判断这个数值发生了精度溢出。

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

NSNumber不同的是,NSDecimalNumberobjCType属性,返回的永远是d,即double,官方文档中有这样的说明:

For a decimal number object, this property always contains “d” (for double).

而在存入NSUserDefaults中时,NSDecimalNumberobjCType方法会被调用,NSUserDefaults应该会通过判断objCType来决定如何将数据持久化到硬盘。由于NSDecimalNumberobjCType永远为d,所以在持久化时,它将以double的形式被持久化,导致了精度溢出。

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容