码迷,mamicode.com
首页 > 其他好文 > 详细

关于数据精度的一点总结

时间:2019-12-20 15:14:39      阅读:109      评论:0      收藏:0      [点我收藏+]

标签:小数   数位   红色   http   精度   ccf   char   超过   www   

说到数据精度,不得不说的,就是数据长度。

这里聊了一下float这个类型,float占4个字节,共4*8=32位。下图是float在内存格式:

技术图片

31:标志位,0表示正数,1表示负数。30-23:指数位,共8位。22-0:小数位,共23位。

 

示例:12345 = ?0011 0000 0011 1001? = 1.1 0000 0011 1001 * 2^13

13为指数,存放到指数位。指数可正可负,所以这8位需要表示-127至128。本例中13保存为13+127 = 140 = ?1000 1100?。

1.1 0000 0011 1001存放在小数位,由于小数点前永远都是1,所以可以省略,只存1 0000 0011 1001,不足23位,后面补0,即保存为1 0000 0011 1001 0000 0000 00

最终保存结果:0 ?1000 1100? 1 0000 0011 1001 0000 0000 00

 

回过头来,再看12345字个数,二进制为1.1 0000 0011 1001 * 2^13,如果小数部份长度超过23位,就无法完整保存了,只能舍弃多余的部份。

比如1.1 0000 0011 1001 0000 0000 001*2^24,蓝色长度为23,实际保存时,只有蓝色部份会保存。

那么这个数,就与1.1 0000 0011 1001 0000 0000 000*2^24在内存中是一样的,但我们知道,这两个数肯定是不一样的,精度丢失!

 

按上述结论,float在整数范围内,精度能完全保存的最大值是1.1111 1111 1111 1111 1111 111*2^23,即1111 1111 1111 1111 1111 1111 = ?16777215?。

这个数+1,就成了1 0000 0000 0000 0000 0000 0000 = 1.0000 0000 0000 0000 0000 0000*2^24 = 167772156。

再+1,就成了1 0000 0000 0000 0000 0000 0001 = 1.0000 0000 0000 0000 0000 0001*2^24 = 167772157。

由于小数长度有23位这个限制,上述的两个数,红色部份都不会保存,即167772156和167772157在内存中保存是一样的: 167772156  =  167772157

 

验证:

int main(int argc, char *argv[])
{
    float j,k;
    j = 16777216;
    k = 16777217;
    cout << j << endl;
    cout << k << endl;
    printf("%f\n",j);
    printf("%f\n",k);
    cout << (j=k?1:0) << endl;
    return 0;
}

输出:

1.67772e+007
1.67772e+007
16777216.000000
16777216.000000
1

 

如果不考虑精度的问题,float能保存的最大值是1.1111 1111 1111 1111 1111 111(1 1111 1111 …… 1111 共128-23=105个1)*2^128 = 3.4028236692093846346337460743177e+38。

由于红色部份不会保存,因此这105位可以是1和0的任意组合,但他们最终都保存为1.1111 1111 1111 1111 1111 111*2^128,仅当这105位都为0,才没有丢失精度,即有2^105-1个数都丢失精度。

 

数据精度是数据存储时,不能回避的问题,在开发过程中,一定要选好正确的数据类型。

关于数据精度的一点总结

标签:小数   数位   红色   http   精度   ccf   char   超过   www   

原文地址:https://www.cnblogs.com/rockmmm/p/12073080.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!