C语言中浮点数的表示方法---浮点数表示引起的误差---IEEE 754关于浮点数的规定

一、表示方法

在计算机中,浮点数一般由三部分组成:符号位+阶码+尾数。

这种浮点数是用科学记数法来表示的,即:浮点数=符号位.尾数×2^阶码。

根据IEEE 754国际标准,常用的浮点数有三种格式:
(1) 单精度浮点数(32位),阶码8位,尾数24位(内含1位符号位)。
(2) 双精度浮点数(64位),阶码11位,尾数53位(内含1位符号位)。
(3) 临时浮点数(80位),阶码15位,尾数65位(内含1位符号位)。


根据IEEE 754标准,符号位也是“0”代表正数;“1”代表负数。

尾数规格化形式,格式如下:1.XXX…X,由于最高位总是1,因此省略,称隐藏位(临时实数则不隐藏)。
    阶码部分,即[E]移=2^(n-1)+E=127+E
    这样,尾数与通常意义的尾数的含义不一致,为了区别,754 中的尾数称为有效数。

二、对上溢和下溢的处理

当运算结果小于规格化浮点数所能表示的最小值时,以前硬件处理策略,或者结果置0或者产生一个下溢陷阱,这两种方案均不能令人满意。

IEEE754处理方法是使用非规格化数。这时阶码为0(即移码-127),尾数没有隐含位,最高位是0。
    这样的结果是降低精度,扩大表示范围。如原来规格化单精度最小值是1.0x2^-126,而非规格化单精度最小值是2^-23 x2^-126=2^-149(只有1位有效位) 。

对上溢用无穷大表示,同时规定:
无穷大+任何数=无穷大
任何有限数÷0=无穷大
任何有限数÷无穷大=0
无穷大÷无穷大=NaN (Not A Number)

C语言中浮点数的表示方法---浮点数表示引起的误差---IEEE 754关于浮点数的规定

三、十进制数转换成浮点数的步骤

1、将十进制数转换成二进制数:

整数部分用2来除,小数部分用2来乘;

2、规格化二进制数:

改变阶码,使小数点前面仅有第一位有效数字;

3、计算阶码:

短型浮点数的阶码加上偏移量7FH
  长型浮点数的阶码加上偏移量3FFH
  扩展型浮点数的阶码加上偏移量3FFFH

4、以浮点数据格式存储。

  把数值的符号位、阶码和尾数合在一起就得到了该数的浮点存储形式。

例1 把十进制数100.25转换成协处理器中的浮点数

解:(1)进制转换:
(100.25)
10=(1100100.01)2
 (2)规格化:
(1100100.01)2=1.10010001×2^6 =1.10010001×2^110
 (3)计算阶码:
       110+01111111=10000101
 (4)数值的符号位为:0
    阶码为:10000101
        尾数为:
1001 0001 0000 0000 0000 000

综合上述可得:
(100.25)10的浮点形式为:
010000101 10010001000000000000000

几个特殊数据的存储规则:

正0:所有的数据位都是0;
    负0:最高位为1,其它的数据位是0;
    正/负无穷:符号位为0/1,阶码位全为1,有效数字全为0;
   NAN:非法的浮点数,阶码位全为1,有效数字不全为0;

四、浮点数转换成十进制数的步骤

该步骤与前面“十进制数转换成浮点数”的步骤是互逆的,其具体步骤如下:

1、分割数字的符号、阶码和有效数字;
2、将偏移阶码减去偏移,得到真正的阶码;
3、把数字写成规格化的二进制数形式;
4、把规格化的二进制数改变成非规格化的二进制数;
5、把非规格化的二进制数转换成十进制数。

例2 把浮点数1100000111001001000000000000转换成十进制数。
解:
(1) 把浮点数 1100000111001001000000000000分割成三部分,可得:
  符号位是1,
阶码    是10000011
尾数    是1001001000000000000
(2) 还原阶码:
      10000011 – 01111111=100
(3) 该浮点数的规格化形式:
1.1001001×24
     (其中前面的“1.”从隐含位而来)
(4) 该浮点数的非规格化形式:
     11001.001
(5) 该浮点数的十进制数为-25.125 (因为符号位为1,所以,该数是负数)

五、误差举例

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	float p = 5.1f;
    int f = (int)(p*100);
    printf("%d\n", f);
	system("pause");
    return 0;
}
C语言中浮点数的表示方法---浮点数表示引起的误差---IEEE 754关于浮点数的规定

原因分析:
5.1的浮点数表示:
5 = (101)
2
0.1 = 0.0 0011 0011 0011 0011 0011 0011 .....(无限循环)

所以 5.1 = 101.0 0011 0011 0011 0011 0011 0011 0011 0011...
 5.1 = 1.010 0011 0011 0011 0011 0011 0011 0011 0011 0011... * 2^2

符号位(1位):0
阶码(8位):2+127=(1000 0001)2
尾数(23位):0100 0110 0110 0110 0110 011
综上5.1的浮点数表示是:
0100 0000 1010 0011 0011 0011 0011 0011
这个数化为10进制整数的时候,由于不可能达到5.1(5.099..),乘以100后被截断为509

六、表示范围、有效数字与截断误差

1、浮点数取值范围:

负数取值范围为 -3.4028235E+38 到 -1.401298E-45,正数取值范围为 1.401298E-45 到 3.4028235E+38。

2、双精度数取值范围:

负值取值范围-1.79769313486231570E+308 到 -4.94065645841246544E-324,正值取值范围为 4.94065645841246544E-324 到 1.79769313486231570E+308。

3、有效数字

单精度数的尾数用23位存储,加上默认的小数点前的1位1,2^(23+1) = 16777216。因为 10^7 < 16777216 < 10^8,所以说单精度浮点数的有效位数是7位。 
双精度的尾数用52位存储,2^(52+1) = 9007199254740992,10^16 < 9007199254740992 < 10^17,所以双精度的有效位数是16位

4、截断误差

发生截断误差的情况

(1)数据越界

表示的数据大于能够表示的最大数,或小于最小数

(2)无限循环

0.1(二进制表示时无限循环)

(3)有效数字位数大于最大有效位数

3.123456789
本文大部分参考了参考1参考2,其中部分表述做了修改

C语言中浮点数的表示方法---浮点数表示引起的误差---IEEE 754关于浮点数的规定,布布扣,bubuko.com

C语言中浮点数的表示方法---浮点数表示引起的误差---IEEE 754关于浮点数的规定

上一篇:基于OpenLayers的地图封装Javascript类定义


下一篇:SAP UI5应用和Hybris Commerce的国际化(internationalization)支持