NSDecimalNumber

2017-12-25  本文已影响17人  移动端_小刚哥

涉及到金额时的计算往往要求保留很高的精度,NSDecimalNumber很好的解决了这个问题,而你不需要再没次都想办法将float或者int型的数值转化为double了

一、问题引出

float a = 0.01;
int b = 99999999;
double c = 0.0;
c = a*b;
NSLog(@"%f",c);     //输出结果为 1000000.000000
NSLog(@"%.2f",c);   //输出结果为 1000000.00

//明显不够精确

如果我们刚开始都是用的double类型的数值,那是没有问题的

double a = 0.01;
double b = 99999999;
double c = 0.0;
c = a*b;
NSLog(@"%f",c);     //输出结果为 999999.990000
NSLog(@"%.2f",c);   //输出结果为 999999.99

//这就对了

但是从float或者int型转为double时会出问题

float a = 0.01;
int b = 999999999;
double c = 0.0;
 NSLog(@"%f",a*(double)b); //9999999.766483
 //精度丢失

通过转化为字符串

NSString *objA = [NSString stringWithFormat:@"%.2f", a];
NSString *objB = [NSString stringWithFormat:@"%.2f", (double)b];
c = [objA doubleValue] * [objB doubleValue];
NSLog(@"%.2f",c);   //输出结果  999999.99

二、NSDecimalNumber的使用

NSDecimalNumber *price1 = [NSDecimalNumber decimalNumberWithString:@"15.99"];
    NSDecimalNumber *price2 = [NSDecimalNumber decimalNumberWithString:@"29.99"];
    NSDecimalNumber *coupon = [NSDecimalNumber decimalNumberWithString:@"5.00"];
    NSDecimalNumber *discount = [NSDecimalNumber decimalNumberWithString:@".90"];
    NSDecimalNumber *numProducts = [NSDecimalNumber decimalNumberWithString:@"2.0"];

//加法
    NSDecimalNumber *subtotal = [price1 decimalNumberByAdding:price2];

//减法
    NSDecimalNumber *afterCoupon = [subtotal decimalNumberBySubtracting:coupon];

//乘法
    NSDecimalNumber *afterDiscount = [afterCoupon decimalNumberByMultiplyingBy:discount];

//除法
    NSDecimalNumber *average = [afterDiscount decimalNumberByDividingBy:numProducts];

//乘方(忘了是不是该这么叫了😂)
    NSDecimalNumber *averageSquared = [average decimalNumberByRaisingToPower:2];


    NSLog(@"Subtotal: %@", subtotal);                       // 45.98
    NSLog(@"After coupon: %@", afterCoupon);                // 40.98
    NSLog((@"After discount: %@"), afterDiscount);          // 36.882
    NSLog(@"Average price per product: %@", average);       // 18.441
    NSLog(@"Average price squared: %@", averageSquared);    // 340.070481

三、Rounding Behavior(不知道怎么翻译,环绕的行为,应该就是末尾处理吧)

Original 1.2 1.21 1.25 1.35 1.27
NSRoundPlain 1.2 1.2 1.3 1.4 1.3
NSRoundDown 1.2 1.2 1.2 1.3 1.2
NSRoundUp 1.2 1.3 1.3 1.4 1.3
NSRoundBankers 1.2 1.2 1.2 1.4 1.3
NSDecimalNumberHandler *roundUp = [NSDecimalNumberHandler
                                       decimalNumberHandlerWithRoundingMode:NSRoundUp
                                       scale:2
                                       raiseOnExactness:NO
                                       raiseOnOverflow:NO
                                       raiseOnUnderflow:NO
                                       raiseOnDivideByZero:YES];

这里我们只抛出了除以0的异常,为什么其他三个异常不抛出呢,这是因为我看了好多文章人家都是没有抛出前三个异常,而我自己又没有都试试,总结起来就是:懒😂

NSDecimalNumber *subtotal = [NSDecimalNumber decimalNumberWithString:@"40.98"];
NSDecimalNumber *discount = [NSDecimalNumber decimalNumberWithString:@".90"];
NSDecimalNumber *total = [subtotal decimalNumberByMultiplyingBy:discount
                                                       withBehavior:roundUp];
NSLog(@"Rounded total: %@", total);

40.98 * 0.9 = 36.882,我们选择了向上保留,所以结果为36.89

四、Comparing NSDecimalNumbers

NSDecimalNumber*discount1 = [NSDecimalNumber decimalNumberWithString:@".85"];
    
NSDecimalNumber*discount2 = [NSDecimalNumber decimalNumberWithString:@".9"];
    
NSComparisonResult result = [discount1 compare:discount2];
    
if (result ==NSOrderedAscending) {
 
     NSLog(@"85%% < 90%%小于");
 
} else if (result == NSOrderedSame) {

     NSLog(@"85%% == 90%%等于");

} else if (result ==NSOrderedDescending) {
 
    NSLog(@"85%% > 90%%大于");

}

这里很多内容都是照抄原文的,在这里向文章作者“梨花落雨”表示感谢,更多内容请参考原文,原文讲解的更加全面

原文地址:<https: www.jianshu.com="" p="" 25d24a184016="">
资源:<http: ios.eezytutorials.com="" nsdecimalnumber-by-example.php=""></http:></https:>

上一篇 下一篇

猜你喜欢

热点阅读