16位data转浮点数 ios

2016-05-25 08:45:24 a158337 阅读数 2036

之前在学习C语言的时候课堂上,老师就强调,不能使用float类型的数字进行相等比较判断。这个也确实听进去了,也明白原因是float是存储是不精确的。但是真正开发实践的时候,或许只有出问题了,才会醒悟:哦,原来是这样。这个问题在高大上的OC上同样存在,稍不注意就会出现问题。

iOS开发中,接受后台的响应,然后转化为模型对象,最终转化为NSString对象,然后控件显示出来。这一切都是那么的自然那么的熟悉。
一个数字,可以定义为number类型,也可以定义为字符串问题。如果后台返回的是字符串类型。在iOS json序列化的时候,会把字符串类型转化为NSString对象,这个一点问题没有。但是如果后台返回的是number类型。json序列化会将number类型转化为NSNumber对象。使用的时候,想当然的会将NSNumber转化为NSString对象。这样做很自然啊,没有问题,也用一两个数字测试了,转化是精确的。测试那边也测试通过了,然后产品上线了。最终,还是出现了问题。不说大数,就10以内的吧。有这么多的转换不精确。(如下图)不信你可以试一下,让后台定义double类型数据66.6,你转化为字符串会发现就是66.59999999999999。测试发现double转化为NSNumber的时候就会出现问题。double表示的字面值和其存储的值一般是不一样的,转化为NSNumber之后,有很大一些数字,在NSNumber的stringValue上会出错。
NSString* json = @”{\”number\”:66.6}”;
NSData* data = [json dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary* dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
id object = dic[@”number”];
NSLog(@”%@”,[object class]);
NSLog(@”%@”,object);
打印结果

__NSCFNumber
66.59999999999999

示例
解决方法可以是把取String的doubleValue,然后再.2f保留两位小数进行构造字符串。千万不能取floatValue,floatValue在大于15万的浮点数字就会出现不精确了(笔者做过遍历测试)。而doubleValue在数十亿的范围内都是字面上精确的。
根本解决方法还是劝后台的同事把请求返回的数据全部设置为String类型
如果涉及到计算的问题,那就只得乖乖转化为NSDecimalNumber对象了。

文/HustBroventure(简书作者)
原文链接:http://www.jianshu.com/p/330c571c3e06
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

2017-05-10 15:40:43 tq471214251 阅读数 1003
当json字典中含有一位及以上小数位时,在使用NSJSONSerialization方法先转为NSData再解析为字符串时有时会出现数据误差,代码如下:

NSString *jsonStr = @"{"number":81.6}";

    

    NSData *jsonData_ = [jsonStrdataUsingEncoding:NSUTF8StringEncoding];

    

    NSError *jsonParsingError_ = nil;

    

   NSDictionary *dic=[NSJSONSerializationJSONObjectWithData:jsonData_ options:NSJSONReadingAllowFragments error:&jsonParsingError_];

    

      NSString *value=dic[@"number"];

    

    NSLog(@"value:%@ ----", value);


打印结果:2016-01-28 09:43:40.827 test[775:19343] value:81.59999999999999 ----

猜想可能是数据转换时精度的问题,因此修改了一下最后解析时的代码,替换了一下value的解析方法如下:

NSString *value=[NSString stringWithFormat:@"%f",[dic[@"number"] doubleValue]];


打印结果: 2016-01-28 09:50:57.627 test[958:23205] value:81.600000 ----

至少数据显示是正常了,当然还可以叫后端开发的兄弟全部返回字符串,也是可以解决这个问题的

2018-12-07 16:58:54 youshaoduo 阅读数 2441

直接上代码:
OC版本的:

    Byte byte[] = {0x47,0x33,0x18,0x00};//{0x00,0x18,0x33,0x47};
    
    NSData * data = [NSData dataWithBytes:byte length:sizeof(byte)];
    int32_t bytes;
    [data getBytes:&bytes length:sizeof(bytes)];
    bytes = OSSwapBigToHostInt32(bytes);
    
    float number;
    memcpy(&number, &bytes, sizeof(bytes));
    NSLog(@"%f", number);

Swift版本的:

    @objc class func floatValue(data: Data) -> Float {
        return Float(bitPattern: UInt32(bigEndian: data.withUnsafeBytes { $0.pointee }))
    }
2017-09-28 11:52:37 prettyfei1123 阅读数 926
#define ARC4RANDOM_MAX      0x100000000

double data = ((double)arc4random() / ARC4RANDOM_MAX) * 6.0f;

2017-06-08 11:03:09 MickDev 阅读数 5739

计算机中float的存储是不精确的。但是真正开发实践的时候,或许只有出问题了,才会醒悟:哦,原来是这样。这个问题在高大上的OC上同样存在,稍不注意就会出现问题。尤其是涉及金融的计算比较数据方面显得格外重要。

iOS开发中,请求后台的接口,然后转化为模型对象,最终转化为NSString对象,然后控件显示出来。这一切都是那么的自然那么的熟悉。但是如果服务器返回的时浮点数格式的字符串 并且客户端还要用到这个数据去做加减乘除 比较大小这类操作,十有八九会出错,如果再涉及金钱利润的时候 这个责任就会无限放大。那么怎样解决呢?下面就看一个例子。


从服务端请求回的数据clearrate字符串类型 需要乘以100再去和另外一个字段exper比较大小 正常的做法是:

   CGFloat clearrate_float = [CUser.clearrate floatValue]*100.0;  

   CGFloat per_assurescale_value = [model.per_assurescale_value floatValue];

     if (clearrate_float > per_assurescale_value) {

        

    }

  这样看似没有问题,但是看一下真是数据就会发现有坑

  真是返回数据是这样的:

   {

    code = 0;

    data =     {

        clearrate = "1.05000000";

    };

   }

  但是实际调试数据是这样的:

     po clearrate_float

     104.99999523162842

  这样 返回的数据和自己转成浮点数在乘以100就会有误差! 那么接下来用到这个数据比较还是加减乘除都会出错!


*这事我们就要用到NSDecimalNumber这个类来处理浮点数的操作了

    //100.0转化成NSDecimalNumber

    NSDecimalNumber *decimalNumber_dit = [NSDecimalNumber decimalNumberWithFloat:100.0];

    //clearrate转化成NSDecimalNumber

    NSDecimalNumber *decimalNumber_clearrate = [NSDecimalNumber decimalNumberWithString:CUser.clearrate];

    

    //两个数想乘

    NSDecimalNumber *afterMultiplying_clearrate = [decimalNumber_clearrate decimalNumberByMultiplyingBy:decimalNumber_dit];


    //per_assurescale_value转化成NSDecimalNumber

    NSDecimalNumber *decimalNumber_per_assurescale_value = [NSDecimalNumber decimalNumberWithString:per_assurescale_value];


    //最终两个浮点数比较大小变成NSDecimalNumber比较大小(如果有需求还可以加减乘除四则运算)

    NSComparisonResult result_clearrate_float = [afterMultiplying_clearrate compare:decimalNumber_per_assurescale_value];


   //NSComparisonResult 的结果分为

     NSOrderedAscending  升序

     NSOrderedSame       相等

     NSOrderedDescending 降序

这样再看一下实际调试po出来的数据:

po decimalNumber_clearrate

1.05

po afterMultiplying_clearrate

105


这样对NSDecimalNumber对象进行对比 四则运算都不会出错了。大家要切记浮点数运算要特别小心!


大家有什么建议 和 学习心得可以留言啊 欢迎大家共同进步微笑