文档章节

iOS开发:Objective-C精确的货币计算

秦无炎
 秦无炎
发布于 2017/05/08 13:44
字数 749
阅读 13
收藏 0

      在iOS开发中,和货币价格计算相关的,需要注意计算精度的问题。即使只是两位小数,也会出现误差。使用float类型运算,是完全不够的。经过一番测试,最后选择使用系统提供的API的NSDecimalNumber来进行更好的解决。

作为一个对外的库,鉴于版本延续,我们保留对外的flaot的类型,不改变接口,选择进行内部适配。

以下是一些基本的测试,

原始数据

 

float a = 0.01;

int b = 99999999;

double c = 0.0;

 

1:使用浮点运算,

 

c = a*b;

NSLog(@"%f",c);

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

 

使用double类型存储没有触及问题的实质,完全不能解决。

 

2011-12-30 11:04:00.121 Untitled[2912:207] 1000000.000000

2011-12-30 11:04:00.123 Untitled[2912:207] 1000000.00

 

 

2:使用类型转换,提高精度

 

c = a*(double)b;

NSLog(@"%f",c);

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

 

Double运算的精度是提高了,可是浮点数的数值早已经出现了精度的不准确,即使存储空间足够,同样还是不准确的数值。

 

2011-12-30 11:04:00.123 Untitled[2912:207] 999999.967648

2011-12-30 11:04:00.124 Untitled[2912:207] 999999.97

 

 

3:通过和NSString的转换,将计算的原始数据转换为纯粹的double类型的数据,这样的计算精度就可以达到要求了。

 

NSString *objA = [NSString stringWithFormat:@"%.2f", a];

NSString *objB = [NSString stringWithFormat:@"%.2f", (double)b];

c = [objA doubleValue] * [objB doubleValue];

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

 

计算的结果还是比较准确的,不过需要做格式化输入和格式化输出的处理。同时使用NSString来转换,这样的写法看起来比较奇怪。

 

2011-12-30 11:04:00.190 Untitled[2912:207] 999999.99

 

 

4:个人还是比较喜欢使用系统提供的类型来进行计算。通过NSDecimalNumber提供的计算方式,可以很好的计算出准确的精度的数据,同时不需要使用格式化输出等。

其计算的精度是比较高,这是官方建议的货币计算的API,对乘除等计算都有单独的API接口来提供。

 

NSString *decimalNumberMutiplyWithString(NSString *multiplierValue,NSString *multiplicandValue)

{

     NSDecimalNumber *multiplierNumber = [NSDecimalNumberdecimalNumberWithString:multiplierValue];

     NSDecimalNumber *multiplicandNumber = [NSDecimalNumberdecimalNumberWithString:multiplicandValue];

     NSDecimalNumber *product = [multiplicandNumber decimalNumberByMultiplyingBy:multiplierNumber];

     return [product stringValue];

}

 

NSLog(@"%@",decimalNumberMutiplyWithString([NSString stringWithFormat:@"%f",a], [NSString stringWithFormat:@"%d",b]));

 

 

 

2011-12-30 11:04:00.251 Untitled[2912:207] 999999.99

 

 

只是测试,所以接口名大致写写,名字取得比较不那么讲究,希望可以表达清楚。

 

总的来说,对于货币计算,应该需要注意精度的问题。同时在运算的时候,应该优先选用框架提供的API,否则,就应该使用足够精度的类型运算,同时对自己写的接口进行足够的说明,要求开发者按照规范来使用。

在自己不能保证足够准确的情况下,用适当的说明的要求来规避责任还是可以接受的。至少被人抱怨两句总比出错强。

 

本文出自 “ArthurChen” 博客,出处http://arthurchen.blog.51cto.com/2483760/761426

本文转载自:

共有 人打赏支持
秦无炎
粉丝 4
博文 122
码字总数 5319
作品 0
朝阳
程序员
10个优秀Objective-C和iOS开发在线视频教程

如果你自己开发iOS应用,你肯定会发现网上有很多资源。学习编程的一个最好的方法就是自己写代码,而开始写代码的最快的方式就是看其他人怎么写。我们从海量视频和学习网站中整理出了我们认为...

mingxun
2014/05/09
0
0
IOS学习笔记——Objective-c基础(一)

最近自学ios,ios的支持语言是Objective-c,所以要学习ios就需要先学习Objective-c语言。当掌握了Objective-c的基础知识之后,我们就可以入手学习iOS开发做出一些自己的应用。 我现在还是...

丛林迷雾
2012/12/30
0
1
我是直接学Swift还是Objective-C?

当我们发布了Swift语言学习课程之后,收到了很多邮件和私信来问自己是否还需要学习C或者Objective-C。此外,人们似乎还在迷惑Swift到底适合iOS开发生态中的哪些部分。通过这篇文章,我希望能...

程序袁_绪龙
2014/09/25
0
2
那些在学习iOS开发前就应该知道的事(part 1)

英文原文:Things I wish I had known before starting iOS development—Part 1 设计师设计出来了一个不错的引导界面,然而当我看到设计稿的时候,我们的app也没几天就要上线了。这个界面模...

TomatosX
2015/06/12
0
0
那些在学习iOS开发前就应该知道的事(part 2)

英文原文:Things I wish I had known before starting iOS development—Part 2 如果你还没读这篇文章的第一部分,请先读完了再来看第二部分。 那些在学习iOS开发前就应该知道的事(part 1)...

TomatosX
2015/06/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

sqlserver 2008 r2 直接下载地址(百度云)

之前下载的sqlserver2008发现不能附加,就卸载了,重新找到了sqlserver2008R2的百度云资源 卸载sqlserver2008还是有点麻烦,不过就是需要删除注册表中的信息 自己来回卸载了3次终于重装sqlse...

dillonxiao
32分钟前
1
0
[Java]JVM调优总结 -Xms -Xmx -Xmn -Xss

JVM调优总结 -Xms -Xmx -Xmn -Xss 博客分类: Java General JVM应用服务器电信CMS算法 堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制;系统的可...

morpheusWB
42分钟前
1
0
C++ std::function 和 std::bind

C++11提供了std::function和std::bind两个工具,用于引用可调用对象。这些可调用对象包括 普通函数,Lambda表达式,类的静态成员函数,非静态成员函数以及仿函数等。引用可调用对象,可以用于...

yepanl
今天
2
0
python:可迭代对象的索引

关于 python的range的用法: 注意是[ 开始,结束)的半开区间,不包括结束 http://www.runoob.com/python/python-func-range.html import collectionsfrom collections import Iterable字符串......

Oh_really
今天
3
0
docker-compose ,docker-stack

1.例子 version: "3"services: php: image: registry.cn-hangzhou.aliyuncs.com/lxepoo/apache-php5 ports: - "38080:80" networks: - my_php_mysql volum......

chenbaojun
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部