金融类 App 中的数字精度问题
在交易市场中,一分一厘都是很重要的,要是开发的时候来个向上向下取整或者四舍五入就会造成纠纷。因此在开发金融类 app 时对数字的精度要求是至关重要的。
而众所周知,计算机中的浮点数计算是不精确的,比如在 Swift 中 print(0.1 + 0.2)
这句代码执行的结果是 0.30000000000000004
而不是 0.3
。产生此种结果的原因此处不再赘述,只说解决的方案。
NSDecimalNumber
NSDecimalNumber
可以用来处理的浮点数的精度问题。它可以使用 Double
类型或者字符串来进行初始化,支持基本的四则运算。对应的方法如下:
- 加法:`adding(_:)
- 减法:
subtracting(_:)
- 乘法:
multiplying(by:)
- 除法:
dividing(by:)
当然,还有其它的一些用法,但是此处只列举常用的一些方法。
1 | let numberA = NSDecimalNumber(value: 0.1) |
这下再运行,可以看到输出结果为 0.3
。
如果是购买东西,假如单价是1.99,数量是2.5,那么结果是4.975,我们要保留两位小数,这时候就要引入 behavior 了。
还是上面的代码:
1 | let behavior = NSDecimalNumberHandler( |
此时输出的结果为 4.98。
此段代码中在两个数相乘时添加了一个 behavior
参数,而 behavior
是一个 NSDecimalNumberHandle
类型。 在这里主要看前两个参数。
第一个是确定小数保留的类型,一共有如下几种:
- NSRoundPlain,四舍五入
- NSRoundDown,只舍不入
- NSRoundUp,只入不舍
- NSRoundBankers,四舍六入,当为5时,确保舍去之后的小数最后一位为偶数
具体的示例如下图表所示:
第二个参数则是设置保留的小数位数,但是不会自动补零,如果需要补零则需要在转为字符串时进行格式化后显示:
1 | print(String(format: "%.2f", result.doubleValue)) |