iOS开发中金钱货币的计算问题
2017-02-28 本文已影响1145人
lym不解释
ios开发中涉及到和货币价格计算相关的,都需要注意计算精度的问题。
服务器有可能返回的金钱是int float double string NSNumber, 单纯的float、double的计算都会出现精度问题,即使只是两位小数,也会出现误差。
苹果为我们提供了NSDecimalNumber的API来处理金钱的计算的问题:
1、字符串转float等不精确问题。
2、精确计算
3、保留小数位数
4、四舍五入及其它的保留小数位数规则
NSDecimalNumber的使用
**1.把相应的类型转换成NSDecimalNumber类型 **
//1、NSString -> NSDecimalNumber
NSDecimalNumber *num1 = [NSDecimalNumber decimalNumberWithString:@"100"];
NSLog(@"%@",num1);
//2、NSNumber -> NSDecimalNumber(基础类型的话,先转成NSNumber)
NSDecimalNumber *num2 = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithInt:50] decimalValue]];
NSLog(@"%@",num2);
2.相关运算
加+
/*加 +
- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//带保留小数位数
*/
NSDecimalNumber *num3 = [num1 decimalNumberByAdding:num2];
NSLog(@"num3 == %@",num3);
减 -
/*减 -
- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//带保留小数位数
*/
NSDecimalNumber *num4 = [num1 decimalNumberBySubtracting:num2];
NSLog(@"num4 == %@",num4);
乘 *
/*乘 *
- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//带保留小数位数
*/
NSDecimalNumber *num5 = [num1 decimalNumberByMultiplyingBy:num2];
NSLog(@"num5 == %@",num5);
除 \
/*除 \
- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;//带保留小数位数
*/
NSDecimalNumber *num6 = [num1 decimalNumberByDividingBy:num2];
NSLog(@"num6 == %@",num6);
比较
/*比较
- (NSComparisonResult)compare:(NSNumber *)decimalNumber;
*/
NSComparisonResult result = [num1 compare:num2];
NSLog(@"result == %ld",(long)result);
保留小数及相关参数含义
// 保留小数
+ (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 保留小数个数
//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.对金钱进行千分位和保留两位小数处理
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使用分类方法处理
- (NSString *)positiveFormat:(NSString *)text{
if(!text || [text floatValue] == 0){
return @"0.00";
}
if (text.floatValue < 1000) {
return [NSString stringWithFormat:@"%.2f",text.floatValue];
};
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setPositiveFormat:@",###.00;"];
return [numberFormatter stringFromNumber:[NSNumber numberWithDouble:[text doubleValue]]];
}