美文网首页
NSDecimalNumber

NSDecimalNumber

作者: 移动端_小刚哥 | 来源:发表于2017-12-25 18:12 被阅读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
    • NSRoundPlain:默认四舍五入
    • NSRoundDown:向下保留
    • NSRoundUp:向上保留
    • NSRoundBankers:如果末尾不是5则按照四舍五入,如果末尾是5,那么末尾5加上倒数第二位,如果和为偶数则进一如果为奇数则舍去
    NSDecimalNumberHandler *roundUp = [NSDecimalNumberHandler
                                           decimalNumberHandlerWithRoundingMode:NSRoundUp
                                           scale:2
                                           raiseOnExactness:NO
                                           raiseOnOverflow:NO
                                           raiseOnUnderflow:NO
                                           raiseOnDivideByZero:YES];
    
    
    • RoundingMode:尾数保留策略
    • scale:保留几位小数
    • raiseOnExactness:精度异常错误是否抛出异常
    • raiseOnOverflow:溢出异常错误是否抛出异常
    • raiseOnUnderflow:不足异常错误是否抛出异常
    • raiseOnDivideByZero:除以0的异常

    这里我们只抛出了除以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%%大于");
    
    }
    
    • Ascending: 升高,就是前边小后边大

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

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

    相关文章

      网友评论

          本文标题:NSDecimalNumber

          本文链接:https://www.haomeiwen.com/subject/aoolgxtx.html