NSNumber 转NSString精度丢失的问题

问题描述:

在iOS开发中:涉及价格金额处理,后台有时会返回Number类型的数据,打印或者经过Json转Model后的NSString有时会出现精度丢失的问题,如果涉及到金额的加减乘除运算问题将暴露得更为明显。

代码示例:

NSArray *numbers = @[
                         @9,
                         @9.00,
                         @9.09,
                         @9.19,
                         @9.29,
                         @9.39,
                         @9.49,
                         @9.59,
                         @9.69,
                         @9.79,
                         @9.89,
                         @9.99,
                         @10.00,
                         @10,
                         ];

    for (int i = 0; i < numbers.count; i++) {
        NSNumber *number = numbers[I];
        NSString *newValue = [number stringValue];
        NSLog(@"newValue:%@,number:%@",newValue,number);
    }
输出.jpg

我们看输出的结果可以看出来将NSNumber转换成NSSting的过程中和存储的时间可能都会出现精度丢失。

问题分析

因为浮点数在计算机中是采用IEEE规定的标准浮点格式,即二进制科学表示法。 在这种表示法中,一个数 S = M * 2 ^ N。

其中N表示阶码,M表示位数(有效数字位)。 例如一个float类型的浮点,在32bit位上,占4个字节,字节表示为
【31】N:【30 ~ 23】 M:【22~0】
a)31位表示符号位: 0正,1负
b)中间8位是阶码位: 表示范围【-128 ~ 127】,对于float类型数据规定其偏移量为127
c)后面23位是有效数字位: 因为科学计数法,整数位定死了是1,所以这里记录的是小数点后面的二进制为

指数N决定它的范围,因为M总是一个以1开头的小数,以float来说即是:-2 ^ 128 ~ 2 ^ 128,即float能表示的数的大小的范围。
而它的精度是由位数(也就是有效的数据位)来决定的, 2 ^ 23 = 8388608,总共7位,表示最多能用7位有效数字,最多能表示到.8388708即小数点后7位,由于不能完全表示全部的7位数,所以它的精度范围是6位~7位。
同理可得double的精度是2 ^ 52 = 4503599627370496, 共16位,所以精度为15 ~ 16位。

总结:

float/double类型的范围和精度的计算方式,对于高精度的计算是不合适的,存在着精度的丢失。相对于float ;double的精度更高一些在用的时间要做好取舍

你可能感兴趣的:(NSNumber 转NSString精度丢失的问题)