iOS 精准计算之 NSDecimalNumber

1,536 阅读2分钟

「这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战」。

前言:

写这篇文章的目的是为了记录之前在开发中遇到的问题,当时后台返回的金额是字符串NSString,而后转成double类型,结果发现转后的数值不准确了,后来查阅了相关的资料,发现苹果官方提供一个精准计算的类。而个也是浮点型精度缺失问题处理的解决方案。

在有些场景下,我们需要精确到每一个小数点,而有些地方则需要显示最大的小数位;

如:[NSString stringWithFormat:@"%.2f",2000/100] 最终显示的是20.00 ,而需求则是显示20;

在项目中,需要对金额或者数字进行精细化的处理,那么我建议你可以使用这个NSDecimalNumber这个类。

NSDecimalNumber

NSDecimalNumber 是iOS中处理精准计算的Number类,它继承自NSNumber;是苹果针对浮点型计算时存在精度计算误差的问题而提供的一个计算类,它是基于10进制的定点计算保证了精度不会缺失。

下面是常用的运算方法,我们可以从方法名中知道它的作用,以下是常用的方法:+ - x /

加法运算 +

- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;

减法运算 -

- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;

乘法运算 x

- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;

除法运算 /

- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;

幂运算

- (NSDecimalNumber *)decimalNumberByRaisingToPower:(NSUInteger)power;
- (NSDecimalNumber *)decimalNumberByRaisingToPower:(NSUInteger)power withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;

10的次方运算

- (NSDecimalNumber *)decimalNumberByMultiplyingByPowerOf10:(short)power;
- (NSDecimalNumber *)decimalNumberByMultiplyingByPowerOf10:(short)power withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;

比较

- (NSComparisonResult)compare:(NSNumber *)decimalNumber;

NSDecimalNumberHandler

NSDecimalNumberHandler这个类允许设置NSDecimalNumber对象四舍五入和处理错误的方式,而不必创建自定义类。

NSDecimalNumberHandler中需要出传入一个四舍五入的类型,即NSRoundingMode枚举类型。

NSRoundingMode有以下四种舍入类型:

  • NSRoundPlain: 四舍五入
  • NSRoundDown: 只舍不入
  • NSRoundUp: 只入不舍
  • NSRoundBankers: 根据保留位数的奇偶性来确定舍入规则
/*
  roundingMode:NSRoundPlain、NSRoundDown、NSRoundUp、NSRoundBankers
  scale: 小数点后的位数
  raiseOnExactness:如果YES,发生精准错误,处理程序将引发异常;否则忽略错误;
  raiseOnOverflow: 如果YES,发生溢出错误,处理程序将引发异常;否则忽略错误;
  raiseOnUnderflow: 如果YES,发生向下溢出错误,处理程序将引发异常;否则忽略错误;
  raiseOnDivideByZero:如果YES,发生除零错误,处理程序将引发异常;否则忽略错误;
**/
+ (instancetype)decimalNumberHandlerWithRoundingMode:(NSRoundingMode)roundingMode  scale:(short)scale  raiseOnExactness:(BOOL)exact  raiseOnOverflow:(BOOL)overflow  raiseOnUnderflow:(BOOL)underflow  raiseOnDivideByZero:(BOOL)divideByZero;

我想大家应该也遇到此类的精准计算的问题吧,除此之外,还有哪些解决方案呢?