欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

浅谈iOS 关于小数精确计算(NSDecimalNumber)

程序员文章站 2023-12-21 12:10:52
做了好一段时间的金融产品,对数字是要非常敏感,差个零点零几都不行,精确度是要非常重视的,将后台传给我的floatvalue转成nsstring,一直没发现问题,最近项目有关...

做了好一段时间的金融产品,对数字是要非常敏感,差个零点零几都不行,精确度是要非常重视的,将后台传给我的floatvalue转成nsstring,一直没发现问题,最近项目有关个人账户的资产显示,发现总是和web和android有点误差,百思不得其解,在stack overflow上面问了一下,发现了nsdecimalnumber这个api,这个类为oc程序提供定点算法功能,它被设计不会损失精度并且可预先设置凑整规则的10进制计算,它比浮点数更好去表达货币,作为代价,它的计算相对复杂,相对耗时。

举个栗子:

float a = 0.01;
int b = 99999999;
double c = 0.0;
c = a * b;
nslog(@"%f",c);
nslog(@"%.2f",c);

2017-08-02 15:41:25.620 decimalnumber[3014:155231] 1000000.000000
2017-08-02 15:41:25.620 decimalnumber[3014:155231] 1000000.00

明显已经已经失真了。

那么我们换个类型,把精度调高,会不会好点呢?

c = a*(double)b;
nslog(@"%f",c);
nslog(@"%.2f",c);

然并卵,

2017-08-02 16:16:32.293 decimalnumber[3144:167125] 999999.967648
2017-08-02 16:16:32.294 decimalnumber[3144:167125] 999999.97

这都是什么鬼,数学白学了。

最后想到了一个方法,我把它转成了字符串,然后再转成double类型,没想到精度就达到要求了

nsstring *astring = [nsstring stringwithformat:@"%.2f", a];

nsstring *bsting = [nsstring stringwithformat:@"%.2f", (double)b];

c = [astring doublevalue] * [bstring doublevalue];

nslog(@"%.2f",c);

2017-08-02 16:27:32.590 decimalnumber[3252:172900] 999999.99

不过看起来有点别扭,转过来转过去的就不说了,一看感觉感觉不专业。下面通过nsdecimalnumber提供计算方式,这是官方建议的货币计算api,精确度比较高,对乘除计算都有单独的接口提供。

nsdecimalnumber *decimalnumber1 = [nsdecimalnumber decimalnumberwithstring:astring];
  
nsdecimalnumber *decimalnumber2 = [nsdecimalnumber decimalnumberwithstring:bstring];
  
nsdecimalnumber *result = [decimalnumber1 decimalnumberbymultiplyingby:decimalnumber2];
  
nslog(@"%@",result);

2017-08-02 16:35:32.779 decimalnumber[3369:177485] 999999.99

这样看起来就舒服多了,精确度也得到了满足

在对于货币的计算显示,要时刻注意精度的问题。优先选用此api,下面是官方的说明nsdecimalnumber

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: