美文网首页iOS开发
OC浮点型精度问题

OC浮点型精度问题

作者: 南飞孤鸿 | 来源:发表于2017-01-16 11:00 被阅读400次

    在OC中经常涉及到浮点型数据转换或者小数点后数据保留,这个就需要考虑到操作时浮点型数据精度问题。一般常用的有几种方法

    一、不考虑四舍五入
    1.直接类型转化
    例如

    float f = 1.5;
    int a;
    a = (int)f;
    NSLog(@"a = %d",a); // 1
    

    输出结果是1。(int)是强制类型转化,丢弃浮点数的小数部分。如果要保存小数点后多少为,就先乘再除

    float f = 3.1415;
    int b = f * 100;
    float c = b/100.0;  
    NSLog(@"b = %f",c); // 3.140000
    

    2.使用NSDecimalNumber
    NSDecimalNumber是NSNumber的子类,比NSNumber的功能更为强大,可以指定一个数的幂,四舍五入等操作。由于NSDecimalNumber精度较高,所以会比基本数据类型费时,所以需要权衡考虑,苹果官方建议在货币以及要求精度很高的场景下使用。

    /**
     *  不四舍五入的将浮点型数据转成字符串
     *
     *  @param number   需要转换的浮点型数据
     *  @param position 保留小数点后几位
     */
    -(NSString *)notRoundNumber:(double)number afterPoint:(int)position{
        
        NSDecimalNumberHandler* roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:position raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:YES];
        NSDecimalNumber *ouncesDecimal = [[NSDecimalNumber alloc] initWithFloat:price];
        NSDecimalNumber *roundedOunces = [ouncesDecimal decimalNumberByRoundingAccordingToBehavior:roundingBehavior];
        NSLog(@"%f", roundedOunces.floatValue);
        return [NSString stringWithFormat:@"%@",roundedOunces];
        
    }
    

    NSDecimalNumberHandler初始化时的关键参数:RoundingMode: 小数保留的类型
    根据官方文档说明, 枚举值分析:
    NSRoundPlain, 四舍五入
    NSRoundDown, 只舍不入
    NSRoundUp, 只入不舍
    NSRoundBankers 四舍六入, 中间值时, 取最近的,保持保留最后一位为偶数

    其他相关参数

    参数 说明
    scale 结果保留几位小数
    raiseOnExactness 发生精确错误时是否抛出异常,一般为NO
    raiseOnOverflow 发生溢出错误时是否抛出异常,一般为NO
    raiseOnUnderflow 发生不足错误时是否抛出异常,一般为NO
    raiseOnDivideByZero 被0除时是否抛出异常,一般为YES

    参照一下图片, 理解上面枚举值:


    RoundingMode.jpg

    3.高斯函数,向下取整

    float f = 1.6;
    int a;
    a = floor(f);
    NSLog(@"a = %d",a); // 1
    

    输出结果是1。floor()方法是向下取整,类似于数学中的高斯函数 .取得不大于浮点数的最大整数,对于正数来说是舍弃浮点数部分,对于负数来说,舍弃浮点数部分后再减1.

    二、考虑四舍五入
    1.使用round函数

    round(12345.6789) 结果为:12346
    round(12345.6789*100)/100 结果为:12345.68
    

    2.通过强制类型转换
    先将浮点型数据加上0.5,再进行转换

    float f = 1.6;
    int a;
    a = (int)(f+0.5);
    NSLog(@"a = %d",a); // 2
    

    三、ceil函数,向上取整

    float f = 1.5;
    int a;
    a = ceil(f);
    NSLog(@"a = %d",a); // 2
    

    ceil()方法是向上取整,取得不小于浮点数的最小整数,对于正数来说是舍弃浮点数部分并加1,对于负数来说就是舍弃浮点数部分.
    精度转换时,经常要先乘以10的多少倍,之后再除以10的多少倍

    相关文章

      网友评论

        本文标题:OC浮点型精度问题

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