前言:
很少寫知識文章或技術文章,邁出第一步勇氣還是要的。加油。。。
正文:
前幾天在專案開發的時候遇到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
}
複製程式碼
結束語
邊踩坑邊學習.蟹蟹