ios開發(fā)中涉及到和貨幣價格計算相關(guān)的异吻,都需要注意計算精度的問題桨仿。
服務(wù)器有可能返回的金錢是int float double string NSNumber, 單純的float羡忘、double的計算都會出現(xiàn)精度問題谎痢,即使只是兩位小數(shù),也會出現(xiàn)誤差卷雕。
蘋果為我們提供了NSDecimalNumber的API來處理金錢的計算的問題:
1节猿、字符串轉(zhuǎn)float等不精確問題。
2爽蝴、精確計算
3、保留小數(shù)位數(shù)
4纫骑、四舍五入及其它的保留小數(shù)位數(shù)規(guī)則
NSDecimalNumber的使用
**1.把相應(yīng)的類型轉(zhuǎn)換成NSDecimalNumber類型 **
//1蝎亚、NSString -> NSDecimalNumber
NSDecimalNumber *num1 = [NSDecimalNumber decimalNumberWithString:@"100"];
NSLog(@"%@",num1);
//2、NSNumber -> NSDecimalNumber(基礎(chǔ)類型的話先馆,先轉(zhuǎn)成NSNumber)
NSDecimalNumber *num2 = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithInt:50] decimalValue]];
NSLog(@"%@",num2);
2.相關(guān)運算
加+
/*加 +
- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//帶保留小數(shù)位數(shù)
*/
NSDecimalNumber *num3 = [num1 decimalNumberByAdding:num2];
NSLog(@"num3 == %@",num3);
減 -
/*減 -
- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//帶保留小數(shù)位數(shù)
*/
NSDecimalNumber *num4 = [num1 decimalNumberBySubtracting:num2];
NSLog(@"num4 == %@",num4);
乘 *
/*乘 *
- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//帶保留小數(shù)位數(shù)
*/
NSDecimalNumber *num5 = [num1 decimalNumberByMultiplyingBy:num2];
NSLog(@"num5 == %@",num5);
除 \
/*除 \
- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//帶保留小數(shù)位數(shù)
*/
NSDecimalNumber *num6 = [num1 decimalNumberByDividingBy:num2];
NSLog(@"num6 == %@",num6);
比較
/*比較
- (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;
//1发框、 NSRoundingMode
// 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 貌似是:
if(四舍五入位 == 5)(四舍五入位(5)+ 保留位 )%2 == 0 ? 入 : 舍 煤墙;
if(四舍五入位 梅惯!= 5) 遵從四舍五入
};
*/
//2、scale 保留小數(shù)個數(shù)
//3仿野、其它:溢出等是否報錯
NSDecimalNumber *num_1 = [NSDecimalNumber decimalNumberWithString:@"1.2"];
NSDecimalNumber *num_2 = [NSDecimalNumber decimalNumberWithString:@"3.1415926"];
NSDecimalNumberHandler *handel = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundBankers scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
NSDecimalNumber *num_3 = [num_1 decimalNumberByMultiplyingBy:num_2 withBehavior:handel];
NSLog(@"num_3 == %@",num_3);
3.對金錢進(jìn)行千分位和保留兩位小數(shù)處理
3.1使用NSNumberFormatter去格式化
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = kCFNumberFormatterCurrencyAccountingStyle;
NSString *newAmount = [formatter stringFromNumber:[NSNumber numberWithLong:[@"10000" integerValue]]];
NSLog(@"newAmount==%@",newAmount);
/*
typedef CF_ENUM(CFIndex, CFNumberFormatterStyle) { // number format styles
kCFNumberFormatterNoStyle = 0,
kCFNumberFormatterDecimalStyle = 1,
kCFNumberFormatterCurrencyStyle = 2,
kCFNumberFormatterPercentStyle = 3,
kCFNumberFormatterScientificStyle = 4,
kCFNumberFormatterSpellOutStyle = 5,
kCFNumberFormatterOrdinalStyle CF_ENUM_AVAILABLE(10_11, 9_0) = 6,
kCFNumberFormatterCurrencyISOCodeStyle CF_ENUM_AVAILABLE(10_11, 9_0) = 8,
kCFNumberFormatterCurrencyPluralStyle CF_ENUM_AVAILABLE(10_11, 9_0) = 9,
kCFNumberFormatterCurrencyAccountingStyle CF_ENUM_AVAILABLE(10_11, 9_0) = 10,
};
*/
3.2 - 工作中常用的工具
WX20190822-190112@2x.png
/// 處理json float double 精度丟失問題
- (NSString *)ym_decimalNumber {
NSString *doubleString = [NSString stringWithFormat:@"%f", self.doubleValue];
NSDecimalNumber *decNumber = [NSDecimalNumber decimalNumberWithString:doubleString];
return [decNumber stringValue];
}
/// 金錢顯示 100,000.00
+ (NSString *)ym_formatDecimalNumber:(NSString *)string {
if (!string || string.length == 0) {
return string;
}
NSNumber *number = @([string doubleValue]);
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = kCFNumberFormatterDecimalStyle;
formatter.positiveFormat = @"###,##0.00";
NSString *amountString = [formatter stringFromNumber:number];
return amountString;
}
/**
金錢顯示 0.00 小數(shù)點后2位 & 符號 變小
*/
+ (NSAttributedString *)ym_priceString:(NSString *)text textColor:(UIColor *)textColor smallFont:(UIFont *)smallFont bigFont:(UIFont *)bigFont symbol:(NSString *)symbol
{
if (!text || text.length == 0) {
text = @"0.00";
}
NSRange range = [text rangeOfString:@"."];
if (range.length == 0) {
return [[NSAttributedString alloc] initWithString:@""];
}
NSArray *texts = [text componentsSeparatedByString:@"."];
NSMutableAttributedString *mStr = [[NSMutableAttributedString alloc]initWithString:symbol.length ? symbol : @"" attributes:@{NSFontAttributeName:smallFont,NSForegroundColorAttributeName:textColor}];
NSAttributedString *bigStr = [[NSAttributedString alloc]initWithString:texts[0] attributes:@{NSFontAttributeName:bigFont,NSForegroundColorAttributeName:textColor}];
NSAttributedString *pointStr = [[NSAttributedString alloc]initWithString:@"." attributes:@{NSFontAttributeName:smallFont,NSForegroundColorAttributeName:textColor}];
NSAttributedString *smallStr = [[NSAttributedString alloc]initWithString:texts[1] attributes:@{NSFontAttributeName:smallFont,NSForegroundColorAttributeName:textColor}];
[mStr appendAttributedString:bigStr];
[mStr appendAttributedString:pointStr];
[mStr appendAttributedString:smallStr];
return mStr;
}
/**
* 中劃線
*/
+ (NSAttributedString *)ym_strikethroughString:(NSString *)text textColor:(UIColor *)textColor font:(UIFont *)font symbol:(NSString *)symbol
{
if (!text || text.length == 0) {
return [[NSAttributedString alloc] initWithString:@""];
}
NSDictionary *dic = @{NSFontAttributeName:font,NSForegroundColorAttributeName:textColor,NSStrikethroughStyleAttributeName: [NSNumber numberWithInt:NSUnderlineStyleSingle]};
NSAttributedString *astr = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@%@", symbol,text] attributes:dic];
return astr;
}