在C语言中用于存储浮点数的有两种类型,单精度float和双精度double。我们知道整形数据或者字符型数据在计算机中存储的是该数据所对应的补码。那么浮点数在计算机中如何存储的呢。无论是单精度还是双精度在存储中都分为三个部分:
1 符号位(Sign) : 0代表正,1代表为负(即浮点数没有无符号的)
2 指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储(注意指数位是指数移位得到的数这部分与取值范围有关)
3 尾数部分(Mantissa):尾数部分(与有效位数有关)
其中float的存储方式如下图所示:
<img id="aimg_z2TUT" class="zoom" file="http://top.embedu.org/uploads/allimg/1604/11-160426100522107.jpg" lazyloadthumb="1" border="0" alt="" />
而双精度的存储方式为:
<img id="aimg_Dbcq2" class="zoom" file="http://top.embedu.org/uploads/allimg/1604/11-16042610053X28.jpg" lazyloadthumb="1" border="0" alt="" />
在分析浮点数的存储是有两个比较重要的概念需要搞清楚:1.有效位数、2.取值范围。
1:有效位数:
单精度数的尾数用23位存储,加上默认的小数点前的1位1,2^(23+1) = 16777216。因为 10^7 < 16777216 < 10^8,所以说单精度浮点数的有效位数是7位。双精度的尾数用52位存储,2^(52+1) = 9007199254740992,10^16 < 9007199254740992 < 10^17,所以双精度的有效位数是16位。
2:取值范围:
要搞清楚浮点数的取值范围必须了解指数位存储的是什么,float中指数位=128+指数,double中指数位= 1024+指数。那么float中指数的范围是-127-128。Double中指数的范围是-1023-1024。那么float的取值范围是-2^128–2^128 即-3.4E+38–3.4E+38double的取值范围-1.79E+308-1.79E+308.
下面我们来验证一下:
我们可以将浮点数写到计算机中,然后去内存中看看浮点数如何存储。当然这种方式不是什么情况都适用,因为在有些情况下我们没有办法查看内存。那么我们可以反向思维的方式去验证。即将浮点数按照浮点数的格式存储的内存中。然后按照浮点数的方式读取出来,与之前的浮点数对比。若相同则可验证。
例:
浮点数5.5 二进制形式为101.1
转化为浮点数存储格式为:0 10000001 0110000000000000000
符号 指数位 尾数部分
即:0x40b00000
下面是C语言程序:
<img id="aimg_phv3M" class="zoom" width="377" height="160" file="http://top.embedu.org/uploads/allimg/1604/11-160426100610219.jpg" border="0" alt="" />
运行结果为:
<img id="aimg_M1474" class="zoom" width="242" height="48" file="http://top.embedu.org/uploads/allimg/1604/11-160426100626245.jpg" border="0" alt="" />
C语言 |