2.4 浮点型数据

2.4.1 浮点型常量

浮点数即实数,在C语言中只有十进制的表现形式,没有十六进制和八进制的表示。实数有以下两种表现形式。

(1)十进制形式的实数由数字和小数点组成(注意必须加小数点),如0.123、123.0。

(2)指数形式的实数用指数记数法的形式来表示。由十进制数,加阶码标志“e”或“E”以及阶码(只能为整数,可以带符号)组成。其一般形式为:

a E n(a为十进制数,n为十进制整数)

其值为a*10n。当“a”的小数点左边有一位(且只能有一位)非零的数字时,这种格式称为规范化的指数形式。如下例都是合法的浮点型数据:

2.1E5(等于2.1*105

3.7E-2(等于3.7*10-2

0.5E7(等于0.5*107

-2.8E-2(等于-2.8*10-2

其中2.1E5、3.7E-2、-2.8E-2都是规范化的指数形式。

以下都不是合法的浮点数:

345(无小数点)

E7(阶码标志E之前无数字)

-5(无阶码标志)

53.-E3(负号位置不对)

2.7E(无阶码)

【例2.4】 浮点型数据的输出。

#include <stdio.h>

void main()

{

  printf("%f\n",356.);     //%f是输出浮点型数据使用的格式符

  printf("%f\n",356);

  printf("%f\n",356.0);

}

2.4.2 浮点型变量

1.浮点型变量在内存中的存放形式

浮点型变量一般占4个字节(32位)内存空间,按指数形式存储。例如,实数9.527在内存中的存放形式如下:

说明:

●小数部分占的位(bit)数越多,数的有效数字越多,精度越高。

●指数部分占的位数越多,能表示的数值范围越大。

2.浮点型变量的分类

C语言的浮点型变量分为单精度型、双精度型和长双精度型三种类型。单精度型的类型关键字为float,一般占4个字节(32位),提供6~7位有效数字。双精度型的类型关键字为double,一般占8个字节,提供15~16位有效数字。长双精度型的类型关键字为long double,一般占16个字节,提供18~19位有效数字。对每一个浮点型变量都应在使用前加以定义。

表2-2列出了C语言中各类浮点型数据所分配的内存字节数及数的表示范围。

表2-2 各类浮点型数据所分配的内存字节数及数的表示范围

浮点型变量定义的格式和书写规则与整型相同。例如:

float x,y;          // 定义x、y为单精度实数

double b;          // 定义 b 为双精度实数

long double c;        // 定义 c 为长双精度实数

3.浮点型数据的舍入误差

由于浮点数是由有限的存储单元组成的,因此能提供的有效数字总是有限的,在有效位以外的数字将被舍弃。

【例2.5】 浮点型数据的舍入误差(一)。

#include <stdio.h>

void main()

{

  float a,b;

  a=123456.789e5;

  b=a+20;

  printf("a=%f\n",a);

  printf("b=%f\n",b);

}

从本例可以看出:由于a的值比20大很多,a+20的理论值是12345678920,而单精度浮点型变量的有效位数只有7位,因此7位以后的数字是无意义的,把20加在后几位上也是无意义的。

【例2.6】 浮点型数据的舍入误差(二)。

#include <stdio.h>

void main()

{

  float a;

  double b;

  a=33333.33333;

  b=33333.33333333333333;

  printf("a=%f\nb=%f\n",a,b);

}

从本例可以看出:

●由于a是单精度浮点型,有效位数只有7位。而整数已占5位,故小数两位后的数字均为无效数字。

●b是双精度型,有效位为16位。但VC6.0规定%f格式中小数后最多保留6位,其余部分四舍五入。

2.4.3 浮点型常量的类型

C语言编译系统将浮点型常量默认为双精度型常量来处理。假设有如下语句:

double var_d;

float var_f;

var_d=3.1415926 * 3.0;

var_f=3.1415926 * 3.0;

由于3.1415926和3.0都是double类型的常量,它们的乘积也是double型的。将结果赋给var_d时,可顺利通过编译;但是,若将结果赋给var_f时,系统给出警告“truncation from const double to float”,提醒用户把一个double常量赋给float型变量,精度会受损失。警告不影响连接和运行,但是用户应了解警告中提出的问题是否影响运行的结果。

当然,我们也可以指定浮点型常量的类型。在浮点型常量后面添上 f 或者 F,编译器就会用float类型来处理这个常量。例如,1.5f、2.1e6F。在后面添上l或者L的话,编译器会用long double类型来处理这个常量。例如,4.1l、50.2E5L。最好用大写L,因为小写l容易和数字1混淆。