先上一段代碼,這段代碼會導致overflow錯誤,使APP發(fā)生crash:
NSString *priceStr = @"";
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:priceStr];
NSDecimalNumber *countNum = [NSDecimalNumber decimalNumberWithString:stringWithNSInteger(NSIntegerMax)];
number = [number decimalNumberByMultiplyingBy:countNum];
在這段代碼中,number的值為:NaN,即:not a number ,非數(shù)值;
而countNum 是一個最大的整數(shù),
最后,將NaN和最大的整數(shù)相乘,導致了overflow的crash。
解決方案代碼如下:
//定義數(shù)值處理的行為
NSDecimalNumberHandler *roundUp = [NSDecimalNumberHandler
decimalNumberHandlerWithRoundingMode:NSRoundBankers
scale:2
raiseOnExactness:NO
raiseOnOverflow:NO
raiseOnUnderflow:NO
raiseOnDivideByZero:NO];
NSString *priceStr = @"";
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:priceStr];
NSDecimalNumber *countNum = [NSDecimalNumber decimalNumberWithString:stringWithNSInteger(NSIntegerMax)];
//使用數(shù)據(jù)處理行為的約定來進行運算,防止crash
number = [number decimalNumberByMultiplyingBy:countNum withBehavior:roundUp];
上面這個例子不會crash了,但是最終number的值為NaN,需要后續(xù)的業(yè)務邏輯進行判斷處理;
NSDecimalNumberHandler 用到的參數(shù),其中:
NSRoundBankers
枚舉,截斷的方式;完整的定義如下:
// Rounding policies :
// Original
// value 1.2 1.21 1.25 1.35 1.27
// Plain 1.2 1.2 1.3 1.4 1.3
// Down 1.2 1.2 1.2 1.3 1.2
// Up 1.2 1.3 1.3 1.4 1.3
// Bankers 1.2 1.2 1.2 1.4 1.3
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
};
scale
小數(shù)點后面的位數(shù)(精度)
raiseOnExactness
The exception raised if there is an exactness error.
raiseOnOverflow
是否拋出溢出錯誤,如果為YES,則APP會捕獲溢出錯誤,這會導致APPcrash;
The exception raised on overflow.
raiseOnUnderflow
The exception raised on underflow.
raiseOnDivideByZero
The exception raised on divide by zero.
補充知識:
判斷一個數(shù)值是否為NaN可以使用系統(tǒng)方法:isnan(x);注:x為數(shù)值類型,不是NSDecimalNumber,更不是NSNumber;
如果要判斷一個NSDecimalNumber 是否為 NAN ,則使用下面的方法:
if([number isEqualToNumber:NSDecimalNumber.notANumber]){
NSLog(@"number is nan");
}else{
NSLog(@"number:%@",number);
}