
2.5 浮点型数据
2.5.1 浮点型常量
表示浮点型常量的形式有两种,如表2.5.1所示,其中e代表10的幂次,幂次可正可负。
表2.5.1 表示浮点型常量的两种形式

注意:字母e(或E)之前必须有数字,且e后面的指数必须为整数。
正确示例:1e3、1.8e−3、−123e−6、−.1e−3。
错误示例:e3、2.1e3.5、.e3、e。
2.5.2 浮点型变量
在C语言中,要使用float关键字或double关键字定义浮点型变量。float型变量占用的内存空间为4字节,double型变量占用的内存空间为8字节。与整型数据的存储方式不同,浮点型数据是按照指数形式存储的。系统把一个浮点型数据分成小数部分(用M表示)和指数部分(用E表示)并分别存放。指数部分采用规范化的指数形式,指数也分正、负(符号位,用S表示),如图2.5.1所示。

图2.5.1 浮点型数据的组成
数符占1位,是0时代表正数,是1时代表负数。表2.5.2是IEEE-754浮点型变量存储标准。
表2.5.2 IEEE-754浮点型变量存储标准

S:S是符号位,用来表示正、负,是1时代表负数,是0时代表正数。
E:E代表指数部分,指数部分运算前都要减去127(这是IEEE-754的规定),因为还要表示负指数。这里的10000001转换为十进制数为129,129 − 127=2,即实际指数部分为2。
M:M代表小数部分,这里为0010 0000 0000 0000 0000 000。底数左边省略存储了一个1,使用的实际底数表示为1.00100000000000000000000。
下面以浮点数4.5(十进制数)为例具体介绍。
计算机并不能计算10的幂次,指数值为2,代表2的2次幂,因此将1.001向左移动2位即可,也就是100.1;然后转换为十进制数,整数部分是4,小数部分是2−1,刚好等于0.5,因此十进制数为4.5。浮点数的小数部分是通过2−1 +2−2 +2−3 +…来近似一个小数的。
下面介绍浮点数的精度控制。
浮点型变量分为单精度(float)型、双精度(double)型和长双精度(longdouble)型三类。如表2.5.3所示,因为浮点数使用的是指数表示法,所以我们不用担心数值的范围,也不用去看浮点数的内存。我们需要注意的是浮点数的精度问题,如图2.5.2所示,我们赋给a的值为1.23456789e10,加20后,应该得到的值为1.234567892e10,但结果却是1.23456788e+010,变得更小了。我们将这种现象称为精度丢失,因为float型数据能够表示的有效数字为7位,最多只保证1.234567e10的正确性,要使结果正确,就需要把a和b均改为double型。
表2.5.3 浮点数的数值范围与有效数字


图2.5.2 验证精度丢失现象的程序
图2.5.2中程序的执行结果如图2.5.3所示。

图2.5.3 图2.5.2中程序的执行结果
思考题:把上例程序中的a和b都改为double型,实际求和后b的值是否正确?