
2.3 小数
小数是我们经常要处理的一种数据,如人的身高、体重、肩宽等数据都会使用到小数。C语言也支持小数形式的数值。
2.3.1 小数的表示

在日常生活中,我们常常会使用到小数,如苹果的单价是3.3元、身高是1.7m等。在C语言中,小数的表示分为小数形式与指数形式。
1. C语言的小数形式
C语言的小数形式包含整数位、小数点与小数位3个部分,如图2.25所示。其中,小数点部分是必须存在的;整数位和小数位部分要至少存在一个。

图2.25 C语言的小数形式
【示例2-12】输出一个省略整数位的小数。
程序如下:

运行程序,输出以下内容:

【示例2-13】输出一个省略小数位的小数。
程序如下:

运行程序,输出以下内容:

2. C语言的指数形式
指数形式又称科学记数法,是一种记数方式。当遇到的数据位数十分大时,使用科学记数法可以方便读/写。
例如,月球的质量约为73 420 000 000 000 000 000 000kg。这样书写月球的质量不但麻烦,而且容易出错。如果使用科学计数法,则月球的质量可以被书写为7.342×1022kg。这样书写月球的质量不但不容易出错,而且指数22可以直接反映出月球的量级,给人以更直观的感觉,如图2.26所示。

图2.26 数据不同表示法的效果
C语言的指数形式包含数字、E/e与整数3个部分,如1.8E-5。其中,数字部分不做要求;E/e部分代替科学记数法中的底数10;整数部分代替科学记数法中的指数,指数可以是正数也可以是负数,如图2.27所示。

图2.27 C语言的指数形式
助记:C语言的指数形式中的字母e/E来源于英文单词exponent(意思为指数)。
【示例2-14】将指数形式的小数以小数形式输出。
程序如下:

运行程序,输出以下内容:

助记:%f中的字母f来源于英文词组floating point(意思为浮点数)。
如果想要输出指数形式的小数,可以使用printf提供的%e或%E。其中,使用%e可以使输出的E/e部分为小写e;使用%E可以使输出的E/e部分为大写E。
助记:%e或%E中的字母e/E来源于英文单词exponent(意思为指数)。
【示例2-15】输出指数形式为小写e的小数。
程序如下:

运行程序,输出以下内容:

【示例2-16】输出指数形式为大写E的小数。
程序如下:

运行程序,输出以下内容:

3. 不精确性
在保存数据时,计算机都是将其以二进制进行处理的。人们在输入数据时,一般输入的是十进制数。所以,当计算机进行运算时,要先将十进制数转换为二进制数再对其进行处理。大部分小数在进行二进制转换时,都无法实现精确的转换,只能取近似值,导致计算机存储的小数是不精确的。
【示例2-17】输出一个小数。
程序如下:

运行程序,输出以下内容:

在日常生活中,小数的不精确性问题并不影响实际计算。毕竟,日常计算的小数位数比较少。例如,1.86元的收款一般都会为1.9元,0.06被四舍五入了。但是当涉及精准运算时,就要规避小数的不精确性问题。
2.3.2 小数类型

在C语言中,按小数的存储方式,将小数分为单精度类型与双精度类型。
1. 双精度类型
当存储的小数数值大,而且要求精度比较高时,可以使用双精度类型存储小数。例如,对于精密定位的数据,就可使用双精度类型存储小数。双精度类型是浮点数的默认存储类型,使用double表示。一个双精度类型小数占8个字节,如图2.28所示。

图2.28 一个双精度类型小数占8个字节
助记:double的意思为两倍的。
【示例2-18】验证双精度类型小数占用的字节长度。
程序如下:

运行程序,输出以下内容:

【示例2-19】验证默认保存的小数占用的字节长度。
程序如下:

运行程序,输出以下内容:

从程序运行结果可以看出,小数在计算机中会被默认保存为8个字节,属于双精度类型。
双精度类型小数的取值范围为(-1.7×10-308)~(1.7×10308),可以精确保存到小数点后15~16位,如图2.29所示。

图2.29 双精度类型范围
【示例2-20】输出一个23位的小数。
程序如下:

运行程序,输出以下内容:

从程序运行结果可以看出,输出的双精度类型小数只能精确到了小数点后的第16位。
注意:%.20f是指输出小数点后20位。
2. 单精度类型
双精度类型小数占用的存储空间较大。如果存储的小数数值比较小,就可以使用单精度类型存储小数。例如,普通小家电的售价基本在1万元以内,整数位和小数位加起来最多6位,这时就可以使用单精度类型进行存储。单精度类型使用float表示。一个单精度类型小数占4个字节,如图2.30所示。

图2.30 一个单精度类型小数占4个字节
注意:在单精度小数后要加后缀字母f或F。
助记:float的意思为浮动。
【示例2-21】验证一个单精度类型小数占几个字节。
程序如下:

运行程序,输出以下内容:

单精度类型小数的取值范围为(-3.4×10-38)~(3.4×1038),且精确保存到小数点后6~7位,如图2.31所示。

图2.31 单精度类型小数的取值范围
【示例2-22】输出一个9位的单精度类型小数。
程序如下:

运行程序,输出以下内容:

在小数后加字母f,表示该小数为单精度类型。从程序运行结果可以看出,该小数只是精确输出小数点后的第7位。
注意:%.10f是指输出小数点后10位。
总结前面讲解的所有小数类型,如表2.5所示。
表2.5 小数类型
