OC,iOS浮点型数据的计算不正确问题

举个例子,有时候float类型的数据参与计算的时候,如果要求精度高的话,往往可能出现各种各样特别神奇的问题,所以NSDecimalNumber 应运而生。NSDecimalNumber继承自NSNumber,用于对浮点型数据的精度计算

举个例子

        float a = 10.33;
        float b = 10.3;
        NSLog(@"a * b = %f",a * b);
        NSLog(@"a + b = %f",a + b);

解决方案

第一种解决方案

如果准确的知道最大的小数保留位数,可以先去整,在计算,比方一下的方法

        float a = 10.33;
        float b = 10.3;
        float c = (a * 100) * (b * 100);
        float d = a * 100 + b * 100;
        NSLog(@"a * b = %f",c / 10000.0);
        NSLog(@"a + b = %f",d / 100.0);

第二种解决方案

   NSDecimalNumber *a = [NSDecimalNumber decimalNumberWithString:@"10.33"];
    NSDecimalNumber *b = [NSDecimalNumber decimalNumberWithString:@"10.3"];
    NSDecimalNumber *c = [NSDecimalNumber decimalNumberWithString:@"2"];
    
    NSLog(@"a + b = %@",[a decimalNumberByAdding:b]);
    NSLog(@"a - b = %@",[a decimalNumberBySubtracting:b]);
    NSLog(@"a * b = %@",[a decimalNumberByMultiplyingBy:b]);
    NSLog(@"a / b = %@",[a decimalNumberByDividingBy:b]);
    NSLog(@"a / b = %@",[a decimalNumberByDividingBy:b]);
    NSLog(@"a的2次方 %@",[a decimalNumberByRaisingToPower:2]);
    NSLog(@"a * 10的2次方 %@",[a decimalNumberByMultiplyingByPowerOf10:2]);
    NSLog(@"a * 10的2次方 %@",[a decimalNumberByMultiplyingByPowerOf10:2]);

NSDecimalNumberHandler的使用
      /*
        NSRoundPlain:四舍五入  NSRoundDown:向下取正   NSRoundUp:向上取正     NSRoundBankers:(特殊的四舍五入,碰到保留位数后一位的数字为5时,根据前一位的奇偶性决定。为偶时向下取正,为奇数时向上取正。如:1.25保留1为小数。5之前是2偶数向下取正1.2;1.35保留1位小数时。5之前为3奇数,向上取正1.4)
        scale:精确到几位小数
        raiseOnExactness:发生精确错误时是否抛出异常,一般为NO
        raiseOnOverflow:发生溢出错误时是否抛出异常,一般为NO
        raiseOnUnderflow:发生不足错误时是否抛出异常,一般为NO
        raiseOnDivideByZero:被0除时是否抛出异常,一般为YES
        */
       
       NSDecimalNumberHandler *roundUp = [NSDecimalNumberHandler
                                          decimalNumberHandlerWithRoundingMode:NSRoundPlain
                                          scale:2
                                          raiseOnExactness:NO
                                          raiseOnOverflow:NO
                                          raiseOnUnderflow:NO
                                          raiseOnDivideByZero:YES];
       NSDecimalNumber * inputNumber = [[NSDecimalNumber alloc]initWithString:@"10.0790001"];
       NSDecimalNumber * number = [inputNumber decimalNumberByRoundingAccordingToBehavior: roundUp];
       NSLog(@"%@",number);//10.08

总结

因为第一种方案需要准确知道精度,如果精度改了,就可能达不到我们想要的效果,代码需要重构,不建议使用。

原文地址:https://www.cnblogs.com/hualuoshuijia/p/14073690.html