美文网首页
浮点数的转化遇到的坑

浮点数的转化遇到的坑

作者: 特拉法尔咖 | 来源:发表于2021-03-11 14:38 被阅读0次

    非原创-搬运记录文章-浮点数的转化遇到的坑

    由于计算机表示小数(包括float和double型小数)都有误差,我们不能直接用等号(==)判断两个小数是否相等。如何两个小数的差的绝对值很小,比如小于 0.0000001,就可以认为它们相等。

    给出除了一个小数比较的方法:

    bool (double num1, double num2) {
        if ((num1 - num2 > -0.0000001) && (num1 - num2) < 0.0000001)
            return true;
        else
            return false;
    }
    

    iOS Objective-c 中将NSString、NSNumber转化成CGFloat会有精度丢失;
    网络传输中,JSON解析数字一般是NSNumber类型,在转化成CGFloat就会造成误差,网络传输数字最好是转成字符串类型。

    OC小数转化

    在OC中是否也有这样的问题,于是乎我测试下,因为考虑到iOS开发时,显示的小数一般不会超过4位:

    CGFloat a = 66.6;
    CGFloat b = 66.66;
    CGFloat c = 66.666;
    CGFloat d = 66.6666;
    
    // CGFloat 转化成 NSNumber(一般会放进NSArray, NSDictionary中)
    NSNumber *an = [NSNumber numberWithFloat:a];
    NSNumber *bn = [NSNumber numberWithFloat:b];
    NSNumber *cn = [NSNumber numberWithFloat:c];
    NSNumber *dn = [NSNumber numberWithFloat:d];
    
    // NSNumber floatValue 转化
    float af = [an floatValue];
    float bf = [bn floatValue];
    float cf = [cn floatValue];
    float df = [dn floatValue];
    
    // NSNumber doubleValue 转化
    double ab = [an doubleValue];
    double bb = [bn doubleValue];
    double cb = [cn doubleValue];
    double db = [dn doubleValue];
    
    // CGFloat 转化成 NSString
    NSString *as = [NSString stringWithFormat:@"%f", a];
    NSString *bs = [NSString stringWithFormat:@"%f", b];
    NSString *cs = [NSString stringWithFormat:@"%f", c];
    NSString *ds = [NSString stringWithFormat:@"%f", d];
    
    // NSString floatValue 转化
    float asf =[as floatValue];
    float bsf =[bs floatValue];
    float csf =[cs floatValue];
    float dsf =[ds floatValue];
    
    // NSString doubleValue 转化
    double asb = [as doubleValue];
    double bsb = [bs doubleValue];
    double csb = [cs doubleValue];
    double dsb = [ds doubleValue];
    

    打印信息:

    == CGFloat 打印
    a: 66.600000
    b: 66.660000
    c: 66.666000
    d: 66.666600
    
    == NSNumber 打印
    an: 66.6
    bn: 66.66
    cn: 66.666
    dn: 66.6666
    
    == NSNumber floatValue 打印
    af: 66.599998
    bf: 66.660004
    cf: 66.666000
    df: 66.666603
    
    == NSNumber doubleValue 打印
    ab: 66.599998
    bb: 66.660004
    cb: 66.666000
    db: 66.666603
    
    == NSString 打印
    as: 66.600000
    bs: 66.660000
    cs: 66.666000
    ds: 66.666600
    
    == NSString floatValue 打印
    asf: 66.599998
    bsf: 66.660004
    csf: 66.666000
    dsf: 66.666603
    
    == NSString doubleValue 打印
    asb: 66.600000
    bsb: 66.660000
    csb: 66.666000
    dsb: 66.666600
    

    NSString doubleValue 转化下来的小数是比较准确的。

    JSON小数转化

    App应用一般数据都是从接口传来的

    测一测JSON传数字:

    NSString *json = @"{"a":66.6, "b":66.66, "c":66.666, "d":66.6666}";
    NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
    NSLog(@"%@", dict);
    for (NSString *key in [dict allKeys]) {
     id object = [dict objectForKey:key];
     NSLog(@"%@: %@ - %@", key, [object class], object);
    
     float xf = [object floatValue];
     double yf = [object doubleValue];
     printf("nf: %f - df: %fn", xf, yf);
    }
    

    打印信息:

    {
     a = "66.59999999999999";
     b = "66.66";
     c = "66.666";
     d = "66.6666";
    }
    d: __NSCFNumber - 66.6666
    nf: 66.666603 - df: 66.666600
    
    b: __NSCFNumber - 66.66
    nf: 66.660004 - df: 66.660000
    
    c: __NSCFNumber - 66.666
    nf: 66.666000 - df: 66.666000
    
    a: __NSCFNumber - 66.59999999999999
    nf: 66.599998 - df: 66.600000
    

    JSON传字符串:

    NSString *json = @"{"a":"66.6","b":"66.66","c":"66.666","d":"66.6666"}";
    NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
    NSLog(@"dict: %@", dict);
    for (NSString *key in [dict allKeys]) {
     id object = [dict objectForKey:key];
     NSLog(@"%@: %@ - %@", key, [object class], object);
    
     float xf = [object floatValue];
     double yf = [object doubleValue];
     printf("nf: %f - df: %fn", xf, yf);
    }
    

    输出信息:

    {
     a = "66.6";
     b = "66.66";
     c = "66.666";
     d = "66.6666";
    }
    d: NSTaggedPointerString - 66.6666
    nf: 66.666603 - df: 66.666600
    
    b: NSTaggedPointerString - 66.66
    nf: 66.660004 - df: 66.660000
    
    c: NSTaggedPointerString - 66.666
    nf: 66.666000 - df: 66.666000
    
    a: NSTaggedPointerString - 66.6
    nf: 66.599998 - df: 66.600000
    

    最后

    聪明的你应该看出:

    1. NSNumber NSString 尽量用 doubleValue 来转化, 千万不能用 floatValue。
    2. 劝后台的同事把请求返回的数据全部设置为 String 类型。
    3. 如果涉及到精确计算的问题,请用 NSDecimalNumber 对象了参考

    参考
    iOS浮点数的转化遇到的坑
    iOS开发可能遇到的坑——浮点数的转化显示问题

    相关文章

      网友评论

          本文标题:浮点数的转化遇到的坑

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