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