前言相比int等整型,float等浮点类型的表示和存储较为复杂,但它又是一个无法回避的话题,那么就有必要对浮点一探究竟了。在计算机中,一般用IEEE浮点近似表示任意一个实数,那么它实际上又是如何表示的呢? 下面的表达式里,i的值是多少,为什么?如果你不确定答案,那么你应该好好看看本文。 float f = 8.25f; IEEE浮点表示IEEE浮点标准用 的形式近似表示一个数。并且将浮点数的位表示划分为三个字段:
在单精度浮点格式(c语言的float)中,s,exp和frac字段分别为1位,8位和23位,而双精度浮点格式(c语言中的double)中,s,exp和frac字段分别为1位,11位和52位。
而根据exp的值,被编码的值可以分为三大类不同的情况。下面进行一一解释。 情况1:规格化的值即最普遍的情况,当exp,即阶码域既不为全0,也不为全1的情况。在这种情况下,阶码字段解释为以偏置(biased)形式表示有符号整数,即E=exp-Bias,exp是无符号数(1~254)。Bias是一个等于的偏置值,对于单精度来说,k=23,Bias=127,因此E的范围是-126~+127。 frac被描述为小数值,且0≤frac<1,其二进制表示为0.frac。尾数定义为 M=1+frac ,则M=1.frac。那么就有1≤M<2,由于总是能够调整阶码E,使得M在范围1≤M<2,所以不需要显示的表示它,这样还能获得一个额外的精度位。也就是说,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的frac部分,等到读取的时候,再把第一位的1加上去。 情况2:非规格化的值当exp,即阶码域为全0时,所表示的数便为非规格化的值,该情况下的阶码值E=1-Bias(注:为从非格式化值转换到格式化值提供了一种方法)。尾数M=frac 非规格化的数有两个作用。
情况3:特殊值有两种
浮点数的范围和有效位对于浮点数,其能表示的数值范围和其有效位如下
可见同比特位数的整型(例如int)要比浮点数(例如float)能表示的数值范围要小很多,但是需要注意的,虽然浮点数能表示的范围大,但是 它却不能精确表示在其范围内的所有实数,也就是说,它只能保证有效位的值是精确的,当表示的数值(小数部分)超过有效位时,所表示的数是无法保证精确的,甚至可以说是错误的。 浮点数的数值范围计算有了前面了基础,我们就可以来计算浮点数的数值范围了。以单精度(float)为例,我们知道它的指数范围(即E)为-126~+127,而M的范围为1≤M<2,实际上,对于单精度,1≤M≤2-2^(-23)(注:23为frac字段所占的比特位)。那么我们就可以得到单精度的最大值为: 我们仅仅以单精度为例,用同样的方法可以计算其他精度的浮点数数值范围,在此不再赘述。 浮点数的有效位有效位也可以理解为我们常说的精度。浮点数的精度是由尾数的位数来决定的。 这也就有了单精度浮点数的有效位为6~7位的结论。根据相似的方法,我们同样可以得到双精度浮点数的有效位为15~16位的结论,这里不再赘述。 浮点数在内存中的存储了解了这么多,我们来看一下一个小数究竟是如何在内存中存储的。以float f = 8.5f为例。其二进制表示为
如果这个时候把这个值作为整型使用,是多少呢?没错,是1091043328
再说几句关于浮点数,需要再说几句:
|
|