C 语言浮点类型简介

目录汇总:C 语言零基础入门教程

整数类型并不适用于所有应用。有些时候需要变量能存储带小数点的数,或者能存储极大数或极小数。这类数可以用浮点(因小数点是“浮动的”而得名)格式进行存储。C 语言提供了 3 种浮点类型,对应三种不同的浮点格式。

  • float:单精度浮点数。
  • double:双精度浮点数。
  • long double:扩展精度浮点数。

当精度要求不严格时(例如,计算带一位小数的温度),float 类型是很适合的类型。double 提供更高的精度,对绝大多数程序来说够用了。long double 支持极高精度的要求,很少会用到。

C 标准没有说明 floatdoublelong double 类型提供的精度到底是多少,因为不同计算机可以用不同方法存储浮点数。大多数现代计算机遵循 IEEE 754 标准(即 IEC 60559)的规范,所以这里也将它作为一个示例。

IEEE 浮点标准

由 IEEE 开发的 IEEE 标准提供了两种主要的浮点数格式:单精度(32 位)和双精度(64 位)。数值以科学记数法的形式存储,每一个数都由三部分组成:符号指数小数。指数部分的位数说明了数值的可能大小程度,而小数部分的位数说明了精度。单精度格式中,指数长度为 8 位,而小数部分占了 23 位。因此,单精度数可以表示的最大值大约是 $3.40\times10^{38}$,其中精度是 6 个十进制数字。

IEEE 标准还描述了另外两种格式:单扩展精度和双扩展精度。标准没有指明这些格式中的位数,但要求单扩展精度类型至少为 43 位,而双扩展精度类型至少为 79 位。想要获得更多有关 IEEE 标准和浮点算术的信息,可以参阅 David Goldberg 在 1991 年 3 月发表的文章“What Every Computer Scientist Should Know About Floating-Point Arithmetic”一文(刊载于 ACM Computing Surveys,第 23 卷第 1 期,第 5~48 页)。

表 4 给出了根据 IEEE 标准实现的浮点类型特征。long double 类型没有显示在此表中,因为它的长度随着机器的不同而变化,而最常见的大小是 80 位和 128 位。

表 4  浮点类型的特征(IEEE 标准)

类型 最小正值 最大值 精度
float $1.175~49\times10^{-38}$ $3.402~82\times10^{38}$ 16 个数字
double $2.225~07\times10^{-308}$ $1.797~69\times10^{308}$ 15 个数字

在不遵循 IEEE 标准的计算机上,表 4 是无效的。事实上,在一些机器上,float 可以有和 double 相同的数值集合,或者 double 可以有和 long double 相同的数值集合。可以在头 <float.h>中找到定义浮点类型特征的宏。

在 C99 中,浮点类型分为两种:一种是实浮点类型,包括 floatdoublelong double 类型;另一种是 C99 新增的复数类型(包括 float _Complexdouble _Complexlong double _Complex)。

一、浮点常量

浮点常量可以有许多种书写方式。例如,下面这些常量全都是表示数 57.0 的有效方式:

1
57.0  57.  57.0e0  57E0  5.7e1  5.7e+1  .57e2  570.e-1

浮点常量必须包含小数点或指数;其中,指数指明了对前面的数进行缩放所需的 10 的幂次。如果有指数,则需要在指数数值前放置字母 E(或 e)。可选符号 +- 可以出现在字母 E(或 e)的后边。

默认情况下,浮点常量以双精度数的形式存储。换句话说,当 C 语言编译器在程序中发现常量 57.0 时,它会安排数据以 double 类型变量的格式存储在内存中。这条规则通常不会引发任何问题,因为在需要时 double 类型的值可以自动转换为 float 类型值。

在某些极个别的情况下,可能会需要强制编译器以 floatlong double 格式存储浮点常量。为了表明只需要单精度,可以在常量的末尾处加上字母 Ff(如 57.0F);而为了说明常量必须以 long double 格式存储,可以在常量的末尾处加上字母 Ll(如 57.0L)。

C99 提供了十六进制浮点常量的书写规范。 十六进制浮点常量以 0x0X 开头(跟十六进制整型常量类似)。这一特性很少用到。

二、读/写浮点数

前面已讨论过,转换说明 %e%f%g 用于读写单精度浮点数。读写 doublelong double 类型的值所需的转换说明略有不同。

  • 读取 double 类型的值时,在 efg 前放置字母 l

    1
    2
    3
    
    double d;
    
    scanf("%lf", &d);
    

    注意: 只能在 scanf 函数格式串中使用 l,不能在 printf 函数格式串中使用。在 printf 函数格式串中,转换 efg 可以用来写 float 类型或 double 类型的值。(C99 允许 printf 函数调用中使用 %le%lf%lg,不过字母 l 不起作用。)

  • 读写 long double 类型的值时,在 efg 前放置字母 L

    1
    2
    3
    4
    
    long double ld;
    
    scanf("%Lf", &ld);
    printf("%Lf", ld);
    

请参阅

(完)

comments powered by Disqus