Float/Double内存结构分析,取值范围、有效位数与内存结构的关系详解(取值范围如何得出?)

偶然间看到float的取值范围是-3.4*10^38到3.4*10^38,然后有效位数是6位或者7位(和编译器有关),突发奇想,想知道float和double的取值范围是如何计算出来的,了解了一下,大概做个总结。

首先说一下Float

1.Float的内存结构

首先我们需要了解一下float的内存结构,弄清楚它在内存中是如何存放的。

float和整形(int等)存放的方式不一样,是以指数方式(科学计数法)的方式存储的。分为三个部分。符号位,指数部分,尾数部分,float占4个字节,总共32位,其中符号位占一位,指数占8位,尾数占23位,数字9.25的存储结构如下图所示:

符号位就是表示当前变量的正负,1正0负

这个例子的表示的float的值是:1.00101 * 2^3,也就是 1001.01,转换成10进制就是9+2^{-1}*0+2^{-2}*1=9.25,具体是为什么呢,可以往下看

指数部分

 float的指数位没有符号,在内存中将指数+127存储。

图中指数部分是1000 0010,对应的十进制数是130,实际上的指数值需要减去127,也就是3,所以例子中对应的指数就是3,

        以这种存储方式,指数的范围是[-127,128],但是float是需要表达NaN(不是一个数字)与Inf(无穷大)的,此时指数位需要来标示,所以全1情况被用掉,另外0特殊表达,指数全0情况也被用掉(当float定义的变量值为0的时候,使用指数全0和尾数全0来表示)。 所以去掉一个最大值,一个最小值,指数表达的范围是:[-126,127]

尾数部分

尾数部分占23位,但是实际上是24位1第一位1被省略,例子中9.25对应的二进制数是1001.01,9+2^{-1}*0+2^{-2}*1=9.25,1001.01可以写成1.00101*2^{3}。我们可以发现,只要我们要存储的数值不为0,任何数都可以写成1.xxxxx *2^{n},所以我们第一位数是可以省略的,不用存储,尾数部分存储的就是小数点后面的内容,小数点也不用存储。我们存在内存中的数就是0010 1000 0000 0000.........(总共23位尾数)

如果要float变量的值为0,那就让尾数和指数全为0,以此来表示0,这是一种特殊情况。

2.float的取值范围分析

所以float的最大值最小值怎么出来呢?

        指数全1的情况(255-127)为了表示特殊的值被用掉了,所以指数最大是254-127=127,尾数省略1和小数点,所以为了使尾数最大,取全1,这时候尾数 = 1+2^{-1}+2^{-2}+2^{-3}+....+2^{-23},这个数非常接近2,所以最后的值就是2*2^127 = 2*1.7014 E38,大概就是3.4E38左右,

最小就是将符号位变成1,表示负数,其他没有任何区别。

double的话指数长度为11位,尾数长度为52位,存储原理是一样的。


大家有什么想法可以和我评论交流~

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值