- 内容提要
- 前言
- 第 1 章 预备知识
- 第 2 章 开始学习 C++
- 第 3 章 处理数据
- 第 4 章 复合类型
- 第 5 章 循环和关系表达式
- 第 6 章 分支语句和逻辑运算符
- 第 7 章 函数——C++的编程模块
- 第 8 章 函数探幽
- 第 9 章 内存模型和名称空间
- 第 10 章 对象和类
- 第 11 章 使用类
- 第 12 章 类和动态内存分配
- 第 13 章 类继承
- 第 14 章 C++中的代码重用
- 第 15 章 友元、异常和其他
- 第 16 章 string 类和标准模板库
- 第 17 章 输入、输出和文件
- 第 18 章 探讨 C++新标准
- 附录 A 计数系统
- 附录 B C++保留字
- 附录 C ASCII 字符集
- 附录 D 运算符优先级
- 附录 E 其他运算符
- 附录 F 模板类 string
- 附录 G 标准模板库方法和函数
- 附录 H 精选读物和网上资源
- 附录 I 转换为 ISO 标准 C++
- 附录 J 复习题答案
3.3 浮点数
了解各种 C++整型后,来看看浮点类型,它们是 C++的第二组基本类型。浮点数能够表示带小数部分的数字,如 M1 油箱的汽油里程数(0.56MPG),它们提供的值范围也更大。如果数字很大,无法表示为 long 类型,如人体的细菌数(估计超过 100 兆),则可以使用浮点类型来表示。
使用浮点类型可以表示诸如 2.5、3.14159 和 122442.32 这样的数字,即带小数部分的数字。计算机将这样的值分成两部分存储。一部分表示值,另一部分用于对值进行放大或缩小。下面打个比方。对于数字 34.1245 和 34124.5,它们除了小数点的位置不同外,其他都是相同的。可以把第一个数表示为 0.341245(基准值)和 100(缩放因子),而将第二个数表示为 0.341245(基准值相同)和 10000(缩放因子更大)。缩放因子的作用是移动小数点的位置,术语浮点因此而得名。C++内部表示浮点数的方法与此相同,只不过它基于的是二进制数,因此缩放因子是 2 的幂,不是 10 的幂。幸运的是,程序员不必详细了解内部表示。重要的是,浮点数能够表示小数值、非常大和非常小的值,它们的内部表示方法与整数有天壤之别。
3.3.1 书写浮点数
C++有两种书写浮点数的方式。第一种是使用常用的标准小数点表示法:
即使小数部分为 0(如 8.0),小数点也将确保该数字以浮点格式(而不是整数格式)表示。(C++标准允许实现表示不同的区域;例如,提供了使用欧洲方法的机制,即将逗号而不是句点用作小数点。然而,这些选项控制的是数字在输入和输出中的外观,而不是数字在代码中的外观。)
第二种表示浮点值的方法叫做 E 表示法,其外观是像这样的:3.45E6,这指的是 3.45 与 1000000 相乘的结果;E6 指的是 10 的 6 次方,即 1 后面 6 个 0。因此,3.45E6 表示的是 3450000,6 被称为指数,3.45 被称为尾数。下面是一些例子:
读者可能注意到了,E 表示法最适合于非常大和非常小的数。
E 表示法确保数字以浮点格式存储,即使没有小数点。注意,既可以使用 E 也可以使用 e,指数可以是正数也可以是负数。(参见图 3.3。)然而,数字中不能有空格,因此 7.2 E6 是非法的。
指数为负数意味着除以 10 的乘方,而不是乘以 10 的乘方。因此,8.33E~4 表示 8.33/104,即 0.000833。同样,电子质量 9.11e~31 kg 表示 0.000000000000000000000000000000911 kg。可以按照自己喜欢的方式表示数字(911 在美国是报警电话,而电话信息通过电子传输,这是巧合还是科学阴谋呢?读者可以自己作出评判)。注意,−8.33E4 指的是−83300。前面的符号用于数值,而指数的符号用于缩放。
记住:
d.dddE+n 指的是将小数点向右移 n 位,而 d.dddE~n 指的是将小数点向左移 n 位。之所以称为“浮点”,就是因为小数点可移动。
图 3.3 E 表示法
3.3.2 浮点类型
和 ANSI C 一样,C++也有 3 种浮点类型:float、double 和 long double。这些类型是按它们可以表示的有效数位和允许的指数最小范围来描述的。有效位(significant figure)是数字中有意义的位。例如,加利福尼亚的 Shasta 山脉的高度为 14179 英尺,该数字使用了 5 个有效位,指出了最接近的英尺数。然而,将 Shasta 山脉的高度写成约 14000 英尺时,有效位数为 2 位,因为结果经过四舍五入精确到了千位。在这种情况下,其余的 3 位只不过是占位符而已。有效位数不依赖于小数点的位置。例如,可以将高度写成 14.162 千英尺。这样仍有 5 个有效位,因为这个值精确到了第 5 位。
事实上,C 和 C++对于有效位数的要求是,float 至少 32 位,double 至少 48 位,且不少于 float,long double 至少和 double 一样多。这三种类型的有效位数可以一样多。然而,通常,float 为 32 位,double 为 64 位,long double 为 80、96 或 128 位。另外,这 3 种类型的指数范围至少是−37 到 37。可以从头文件 cfloat 或 float.h 中找到系统的限制。(cfloat 是 C 语言的 float.h 文件的 C++版本。)下面是 Borland C++ Builder 的 float.h 文件中的一些批注项:
注意:
有些 C++实现尚未添加头文件 cfloat,有些基于 ANSI C 之前的编译器的 C++实现没有提供头文件 float.h。
程序清单 3.8 演示了 float 和 double 类型及它们表示数字时在精度方面的差异(即有效位数)。该程序预览了将在第 17 章介绍的 ostream 方法 setf( )。这种调用迫使输出使用定点表示法,以便更好地了解精度,它防止程序把较大的值切换为 E 表示法,并使程序显示到小数点后 6 位。参数 ios_base::fixed 和 ios_base::floatfield 是通过包含 iostream 来提供的常量。
程序清单 3.8 floatnum.cpp
下面是该程序的输出:
1.程序说明
通常 cout 会删除结尾的零。例如,将 3333333.250000 显示为 3333333.25。调用 cout.setf( ) 将覆盖这种行为,至少在新的实现中是这样的。这里要注意的是,为何 float 的精度比 double 低。tub 和 mint 都被初始化为 10.0/3.0—3.333333333333333333……由于 cout 打印 6 位小数,因此 tub 和 mint 都是精确的。但当程序将每个数乘以一百万后,tub 在第 7 个 3 之后就与正确的值有了误差。tub 在 7 位有效位上还是精确的(该系统确保 float 至少有 6 位有效位,但这是最糟糕的情况)。然而,double 类型的变量显示了 13 个 3,因此它至少有 13 位是精确的。由于系统确保 15 位有效位,因此这就没有什么好奇怪的了。另外,将 tub 乘以一百万,再乘以 10 后,得到的结果不正确,这再一次指出了 float 的精度限制。
cout 所属的 ostream 类有一个类成员函数,能够精确地控制输出的格式—字段宽度、小数位数、采用小数格式还是 E 格式等。第 17 章将介绍这些选项。为简单起见,本书的例子通常只使用<<运算符。有时候,这种方法显示的位数比需要的位数多,但这只会影响美观。如果您介意这种问题,可以浏览第 17 章,了解如何使用格式化方法。然而,在这里就不作过多的解释了。
读取包含文件
C++源文件开头的包含编译指令总是有一种魔咒的力量,新手 C++程序员通过阅读和体验来了解哪个头文件添加哪些功能,再一一包含它们,以便程序能够运行。不要将包含文件作为神秘的知识而依赖;可以随便打开、阅读它们。它们都是文本文件,因此可以很轻松地阅读它们。被包含在程序中的所有文件都存在于计算机中,或位于计算机可以使用的地方。找到那些要使用的包含文件,看看它们包含的内容。您将会很快地知道,所使用的源文件和头文件都是知识和信息的很好来源—在有些情况下,它们都是最好的文档。当使用更复杂的包含文件,并开始在应用程序中使用其他非标准库时,这种习惯将非常有帮助。
3.3.3 浮点常量
在程序中书写浮点常量的时候,程序将把它存储为哪种浮点类型呢?在默认情况下,像 8.24 和 2.4E8 这样的浮点常量都属于 double 类型。如果希望常量为 float 类型,请使用 f 或 F 后缀。对于 long double 类型,可使用 l 或 L 后缀(由于 l 看起来像数字 1,因此 L 是更好的选择)。下面是一些示例:
3.3.4 浮点数的优缺点
与整数相比,浮点数有两大优点。首先,它们可以表示整数之间的值。其次,由于有缩放因子,它们可以表示的范围大得多。另一方面,浮点运算的速度通常比整数运算慢,且精度将降低。程序清单 3.9 说明了最后一点。
程序清单 3.9 fltadd.cpp
注意:
有些基于 ANSI C 之前的编译器的老式 C++实现不支持浮点常量后缀 f。如果出现这样的问题,可以用 2.34E+22 代替 2.34E+22f,用(float) 1.0 代替 1.0f。
该程序将数字加 1,然后减去原来的数字。结果应该为 1。下面是在某个系统上运行时该程序的输出:
问题在于,2.34E+22 是一个小数点左边有 23 位的数字。加上 1,就是在第 23 位加 1。但 float 类型只能表示数字中的前 6 位或前 7 位,因此修改第 23 位对这个值不会有任何影响。
将类型分类
C++对基本类型进行分类,形成了若干个族。类型 signed char、short、int 和 long 统称为符号整型;它们的无符号版本统称为无符号整型;C++11 新增了 long long。bool、char、wchar_t、符号整数和无符号整型统称为整型;C++11 新增了 char16_t 和 char32_t。float、double 和 long double 统称为浮点型。整数和浮点型统称算术(arithmetic)类型。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论