NSDecimalNumber 主要应用于需要高精度处理的数据,基本使用方法如下:
1.加减乘除计算
- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber;
2.四舍五入 NSRoundingMode
typedef NS_ENUM(NSUInteger, NSRoundingMode) {
NSRoundPlain, // Round up on a tie
NSRoundDown, // Always down == truncate
NSRoundUp, // Always up
NSRoundBankers // on a tie round so last digit is even
};
3.数值大小比较
- (NSComparisonResult)compare:(NSNumber *)decimalNumber;
NSComparisonResult 结果
typedef NS_CLOSED_ENUM(NSInteger, NSComparisonResult) {
NSOrderedAscending = -1L,
NSOrderedSame,
NSOrderedDescending
};
4.NSDecimalNumberHandler 类 用于做一些基本的设置,包括容错的设置,如下:
NSDecimalNumberHandler* roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:position raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
5.对于代码中未做错误处理的补救方法
NSDecimalNumber 关于加减乘除的方法都可以包含一个 NSDecimalNumberBehaviors 参数,
- (NSDecimalNumber *)decimalNumberByRoundingAccordingToBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
如果代码中都未做设置,也可以通过继承<NSDecimalNumberBehaviors>协议,重写 exceptionDuringOperation 方法达到同样的目的,以下只是做了除数为0的异常处理
-(NSRoundingMode)roundingMode
{
return NSRoundDown;
}
-(short)scale
{
return NSDecimalNoScale;
}
-(NSDecimalNumber*)exceptionDuringOperation:(SEL)operation error:(NSCalculationError)error leftOperand:(NSDecimalNumber *)leftOperand rightOperand:(NSDecimalNumber *)rightOperand
{
if (error == NSCalculationDivideByZero) {
return [NSDecimalNumber zero];
}
return nil;
}
另外也可以通过 Method swizzled 达到同样的目的,使所有不包含 NSDecimalNumberBehaviors 的方法都被替换掉,遵循统一设置
+(void)load
{
[super load];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class_NSDecimalNumber = NSClassFromString(@"NSDecimalNumber");
Method original_NSDecimalNumber = class_getInstanceMethod(class_NSDecimalNumber, @selector(decimalNumberByDividingBy:));
Method swizzled_NSDecimalNumber = class_getInstanceMethod(class_NSDecimalNumber, @selector(my_decimalNumberByDividingBy:));
method_exchangeImplementations(original_NSDecimalNumber, swizzled_NSDecimalNumber);
});
}
-(NSDecimalNumber*)my_decimalNumberByDividingBy:(NSDecimalNumber*)number
{
return [(NSDecimalNumber*)self decimalNumberByDividingBy:number withBehavior:self];
}