美文网首页
iOS小记--Long Long型和double型转换的坑

iOS小记--Long Long型和double型转换的坑

作者: 原鸣清 | 来源:发表于2019-10-08 09:04 被阅读0次

    先看一段代码:

        NSDictionary *dict = [self dictFromResponseObject:responseData];
        CYBasicResponce *response = [responseClass mj_objectWithKeyValues:dict];
    

    上面的代码看起来很和谐,就是把从后台请求获取到的字典(底层库处理了JSON解析)转换成对象,以供处理数据逻辑。但是谁曾想这里有个大坑呢,就像我在下边注释里写的。

    /**      mj_objectWithKeyValues:方法中将数值类型数据先转
             double型,再转回来,比如说long long型数值a,会先被转为(double)a;
             再转回(long long)a;对于大多数数字不会有什么问题,但是当整数有效值
             长度超过15时,由于浮点数的取舍问题,这个值会发生变化,不再是你之前以为
             的样子。对的,我们的uid就是这样的一个大数,不然我怎么会遭遇这个bug,并
             且在这里写上这么长一段注释🐶。
             156939277061174208 //转化后uid
             156939277061174202 //实际uid
             代码可证:
                    long long a = 15693927706117420;
                    double b = (double)a;
                    long long c = (long long)b;
                    printf("A = %lld\n",a);
                    printf("B = %f\n",b);
                    printf("C = %lld\n",c);
             Console:
                    A = 15693927706117420
                    B = 15693927706117420.000000
                    C = 15693927706117420
                    Program ended with exit code: 0
             解决方法:
                    将uid特殊处理,重新set。
             */
            NSNumber *uid = dict[@"uid"];
            if (uid) {
                [response setValue:uid forKey:@"uid"];
            }
    

    问题代码在NSObject+MJKeyValue.h这个文件的第163行(我用的是3.1.2版本),如下:

    162    NSDecimalNumber *decimalValue = [NSDecimalNumber decimalNumberWithString:oldValue];
    163    value = decimalValue == [NSDecimalNumber notANumber] ? @(0) : @(decimalValue.doubleValue);
    

    查了下原因,大致可以归结到浮点数的向偶舍入,其间的技术细节这位大神在系列博客里说的很清楚,有兴趣有时间可以读下。

    相关文章

      网友评论

          本文标题:iOS小记--Long Long型和double型转换的坑

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