1 实型常量的表示方法
实数(real number)又称浮点数(floating-point number)。实数有两种表示形式:
(1)十进制小数形式。它由数字和小数点组成(注意必须有小数点)。.123、123.、123.0、0.0都是十进制小数形式。
(2)指数形式。如123e3或123E3都代表123x103。但注意字母e(或E)之前必须有数字,且e后面的指数必须为整数,如e3、2.1e3.5、.e3、e等都不是合法的指数形式。
一个实数可以有多种指数表示形式。例如123.456可以表示为123.456e0、12.3456e1、1.23456e2、0.123456e3、0.0123456e4、0.00123456e5等。把其中的1.23456e2称为“规范化的指数形式”,即在字母e(或 E)之前的小数部分中,小数点左边应有一位(且只能有一位)非零的数字。例如2.3478e2、3.0999E5、6.46832e12都属于规范化的指数形式,而12.908e10、0.4578e3、756e0则不属于规范化的指数形式。一个实数在用指数形式输出时,是按规范化的指数形式输出的。例如,指定将实数5689.65按指数形式输出,必然输出5.68965e+003,而不会是0.568965e+004或56.8965e+002。
2 实型变量
1.实型数据在内存中的存放形式
一个实型数据一般在内存中占4个字节(32位)。与整型数据的存储方式不同,实型数据是按照指数形式存储的。系统把一个实型数据分成小数部分和指数部分分别存放,小数部分采用规范化的指数方式表示。实数3.14159在内存中的存放形式如图3.7示意。
图中是用十进制数来示意的,实际上在计算机中是用二进制数来表示小数部分以及用2的幂次来表示指数部分的。
在4个字节(32 位)中,究竟用多少位来表示小数部分,多少位来表示指数部分,标准C并无具体规定,由各C编译系统自定。不少C编译系统以24位表示小数部分(包括符号),以8位表示指数部分(包括指数的符号)。小数部分占的位(bit)数愈多,数的有效数字愈多,精度愈高。指数部分占的位数愈多,则能表示的数值范围愈大。
2.实型变量的分类
C实型变量分为单精度(float)型、双精度(double)型和长双精度(long double)型三类。有关规定见表3.2。
表3.2 实型数据
类型 | 比特数 | 有效数字 | 数值范围 |
float | 32 | 6~7 | -3.4x10-38--~3.4x1038 |
double | 64 | 15~16 | -1.7x10-308~1.7x10308 |
long double | 128 | 18~19 | -1.2x10-4932~1.2x104932 |
ANSIC并未具体规定每种类型数据的长度、精度和数值范围。有的系统将double型所增加的32位全用于存放小数部分,这样可以增加数值的有效位数,减少舍人误差。有的系统则将所增加的位(bit)用于存放指数部分,这样可以扩大数值的范围。表3.2列出的是微机上常用的C编译系统(如TurboC,MSC,BorlandC)的情况。应当了解,不同的系统会有差异。
对每一个实型变量都应在使用前加以定义。如:
float x,y; (指定x、y为单精度实数)
double z; (指定z为双精度实数)
long double t; (指定t为长双精度实数)
在初学阶段,对long double型用得较少,因此我们不准备作详细介绍。读者只要知道有此类型即可。
3.实型数据的舍入误差
由于实型变量是用有限的存储单元存储的,因此能提供的有效数字总是有限的,在有效位以外的数字将被舍去。由此可能会产生一些误差。例如,a加20的结果显然应该比 a大。请分析下面的程序:
例3.4 实型数据的舍入误差。
main( )
{float a,b;
a=123456.789e5;
b=a+20;
printf("%f\n",b);
}
程序内 printf 函数中的“%f”是输出一个实数时的格式符。程序运行时,输出b的值与a相等。原因是:a的值比20大很多,a+20的理论值应是12345678920,而一个实型变量只能保证的有效数字是7位有效数字,后面的数字是无意义的,并不准确地表示该数。运行程序得到的a和b的值都是12345678848.000000,可以看到,前8位是准确的,后几位是不准确的,把20加在后几位上,是无意义的。应当避免将一个很大的数和一个很小的数直接相加或相减,否则就会“丢失”小的数。与此类似,用程序计算1.0/3*3的结果并不等于1。
3 实型常量的类型
C编译系统将实型常量作为双精度来处理。例如已定义一个实型变量f,有如下语句:
f=2.45678*4523.65
系统将2.45678和 4523.65按双精度数据存储(占64位)和运算,得到一个双精度的乘积,然后取前7位赋给实型变量f。这样做可以保证计算结果更精确,但是运算速度降低了。可以在数的后面加字母f或F(如1.65f、654.87F),这样编译系统就会按单精度(32位)处理。
一个实型常量可以赋给一个float型、double 型或long double变量。根据变量的类型截取实型常量中相应的有效位数字。假如a已指定为单精度实型变量:
float a;
a=111111.111;
由于float 型变量只能接收7位有效数字,因此最后两位小数不起作用。如果a改为 double 型,则能全部接收上述9位数字并存储在变量a中。