大家都會(huì)在開發(fā)中遇到, 處理一個(gè)浮點(diǎn)型的數(shù)據(jù)時(shí), 有時(shí)候會(huì)有一個(gè)精度的丟失, 造成數(shù)據(jù)不準(zhǔn)確. float的精度為6-7位有效數(shù)字,double的精度為15-16位,所以在處理浮點(diǎn)型數(shù)據(jù)時(shí)盡量選擇double類型。但是在一些涉及數(shù)據(jù)計(jì)算,大小比較時(shí)責(zé)任重大,非常容易出錯(cuò),因此使用系統(tǒng)自帶的NSDecimalNumber做處理, 能解決這問題。
1.NSDecimalNumber
NSDecimalNumber是NSNumber的不可變子類。蘋果針對(duì)浮點(diǎn)型計(jì)算時(shí)存在精度計(jì)算誤差的問題而提供的一個(gè)計(jì)算類,它是基于10進(jìn)制的定點(diǎn)計(jì)算保證了精度不會(huì)缺失。同時(shí)也可以定制精度的取正類型:向上取正、向下去正、四舍五入等。相對(duì)與浮點(diǎn)類型的計(jì)算,NSDecimalNumber提供了更加精準(zhǔn)的計(jì)算。
2.NSDecimalNumber 基本運(yùn)算
//1、字符串 -> NSDecimalNumber
NSDecimalNumber *num1 = [NSDecimalNumber decimalNumberWithString:@"123"];
//2、NSNumber -> NSDecimalNumber(基礎(chǔ)類型的話,先轉(zhuǎn)成NSNumber)
NSDecimalNumber *num2 = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithInt:123] decimalValue]];
//相關(guān)運(yùn)算
/* +
- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//帶保留小數(shù)位數(shù)
*/
NSDecimalNumber *num3 = [num1 decimalNumberByAdding:num2];
/*減 -
- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//帶保留小數(shù)位數(shù)
*/
NSDecimalNumber *num4 = [num1 decimalNumberBySubtracting:num2];
/*乘 *
- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//帶保留小數(shù)位數(shù)
*/
NSDecimalNumber *num5 = [num1 decimalNumberByMultiplyingBy:num2];
/*除 \
- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//帶保留小數(shù)位數(shù)
*/
NSDecimalNumber *num6 = [num1 decimalNumberByDividingBy:num2];
/*比較
- (NSComparisonResult)compare:(NSNumber *)decimalNumber;
*/
NSComparisonResult result = [num1 compare:num2];
NSLog(@"result == %ld",(long)result);
//保留小數(shù)及相關(guān)參數(shù)含義
/*保留小數(shù)
+ (instancetype)decimalNumberHandlerWithRoundingMode:(NSRoundingMode)roundingMode scale:(short)scale raiseOnExactness:(BOOL)exact raiseOnOverflow:(BOOL)overflow raiseOnUnderflow:(BOOL)underflow raiseOnDivideByZero:(BOOL)divideByZero;
*/
// 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 (特殊的四舍五入,碰到保留位數(shù)后一位的數(shù)字為5時(shí),根據(jù)前一位的奇偶性決定。為偶時(shí)向下取正,為奇數(shù)時(shí)向上取正。如:1.25保留1為小數(shù)。5之前是2偶數(shù)向下取正1.2;1.35保留1位小數(shù)時(shí)。5之前為3奇數(shù),向上取正1.4)
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ù)的個(gè)數(shù)(為0的無效小數(shù)后自動(dòng)過濾).
//Exactness:進(jìn)度異常、Overflow:向上溢出、Underflow:向下溢出、DivideByZero:除數(shù)為0。當(dāng)參數(shù)為YES出錯(cuò)會(huì)
拋出異常,為NO時(shí)忽略異常。返回nil.
NSDecimalNumberHandler *roundUp = [NSDecimalNumberHandler
decimalNumberHandlerWithRoundingMode:NSRoundUp
scale:2
raiseOnExactness:NO
raiseOnOverflow:NO
raiseOnUnderflow:NO
raiseOnDivideByZero:YES];
所以在處理有關(guān)浮點(diǎn)型數(shù)據(jù),后臺(tái)傳字符串的格式,防止丟失精度。