前言:
很少写知识文章或技术文章,迈出第一步勇气还是要的。加油。。。
正文:
前几天在项目开发的时候遇到double类型精度不准确导致代码不能按正常逻辑处理,这个让我很纳闷,因为前几个版本都没有出现这类型的错。试过用NSString来处理,可是加减乘除还是要转换成基本类型,又会计算精度误差。
问题如图下:
刚好有个判断逻辑是:
if (payAmount1 + payAmount2 < [paySumAmount doubleValue]) {
UIAlert(@"提示",@"输入的总金额不足以支付订单,请重新输入", @"确定", nil);
return;
}
复制代码
很尴尬,明明输入的金额满足支付,却一直被被拦住。
为了避免偶尔性出现计算精度问题,用NSDecimalNumber 可以完美的处理。不多说上相关代码。
1.关于NSDecimalNumber属性和方法
/*
声明:
mantissa:为基数
exponent:为幂的次方 例如 传2 相等于 10*10
flag: yes代表正数,no代表负数
return:返回对象NSDecimalNumber
*/
- (instancetype)initWithMantissa:(unsigned long long)mantissa exponent:(short)exponent isNegative:(BOOL)flag;
+ (NSDecimalNumber *)decimalNumberWithMantissa:(unsigned long long)mantissa exponent:(short)exponent isNegative:(BOOL)flag;
+ (NSDecimalNumber *)decimalNumberWithString:(nullable NSString *)numberValue;
- (NSNumber *)initWithDouble:(double)value;
- (NSNumber *)initWithFloat:(float)value;
- (NSNumber *)initWithBool:(BOOL)value;
~
~
~
@property (class, readonly, copy) NSDecimalNumber *zero;//0
@property (class, readonly, copy) NSDecimalNumber *one;//1
@property (class, readonly, copy) NSDecimalNumber *minimumDecimalNumber;//最小值
@property (class, readonly, copy) NSDecimalNumber *maximumDecimalNumber;//最大值
@property (class, readonly, copy) NSDecimalNumber *notANumber;//无值
//加法
- (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;
//乘法
- (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;
//幂运算
- (NSDecimalNumber *)decimalNumberByMultiplyingByPowerOf10:(short)power;
- (NSDecimalNumber *)decimalNumberByMultiplyingByPowerOf10:(short)power withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
//四舍五入
- (NSDecimalNumber *)decimalNumberByRoundingAccordingToBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
//比较2个值
- (NSComparisonResult)compare:(NSNumber *)decimalNumber;
复制代码
2.NSDecimalNumberHandler 用法 -- 声明四舍五入规则
@property (class, readonly, strong) NSDecimalNumberHandler *defaultDecimalNumberHandler;
// rounding mode: NSRoundPlain //默认NSRoundPlain
// scale: No defined scale (full precision)//保留几位小数
// ignore exactnessException (return nil) //转换异常抛出
// raise on overflow, underflow and divide by zero.//转换异常抛出
/**
NSRoundingMode:
{
NSRoundPlain:四舍五入 2.56 ->2.6 2.44 -> 2.4
NSRoundDown:向下取值 2.56->2.5 2.44->2.4
NSRoundUp:向上取值 2.56 ->2.6 2.44->2.5
NSRoundBankers: NSRoundPlain一样(如果大神们有其他特殊例子麻烦告诉一声)
}
scale:保留几个小数
其他:溢出异常报错 为No就可以了。
*/
- (instancetype)initWithRoundingMode:(NSRoundingMode)roundingMode scale:(short)scale raiseOnExactness:(BOOL)exact raiseOnOverflow:(BOOL)overflow raiseOnUnderflow:(BOOL)underflow raiseOnDivideByZero:(BOOL)divideByZero
+ (instancetype)decimalNumberHandlerWithRoundingMode:(NSRoundingMode)roundingMode scale:(short)scale raiseOnExactness:(BOOL)exact raiseOnOverflow:(BOOL)overflow raiseOnUnderflow:(BOOL)underflow raiseOnDivideByZero:(BOOL)divideByZero;
复制代码
3.简单用法
NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:position raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
NSDecimalNumber *decimal1 = [[NSDecimalNumber alloc] initWithDouble:15.384];
NSDecimalNumber *decimal2 = [[NSDecimalNumber alloc] initWithDouble:13.555];
//加法
NSDecimalNumber *result = [decimal1 decimalNumberByAdding:decimal2 withBehavior:roundingBehavior];//28.94
//减法
NSDecimalNumber *result1 = [decimal1 decimalNumberBySubtracting:decimal2 withBehavior:roundingBehavior];//1.82
//比较
if ([result compare:result1] == NSOrderedAscending) { //升序
//result < result1
}else if ([result compare:result1] == NSOrderedDescending) { //降序
//result > result1
}else if ([result1 compare:result1] == NSOrderedSame) {
//result = result1
}
复制代码
结束语
边踩坑边学习.蟹蟹