1、浮点数的概念
浮点数可以表示诸如 2.5、3.1415和100033.23 这样的数字,即带小数部分的数字。计算机将这样的值分成两部分储存。一部分表示值,另一部分用于对值进行放大和缩小。比如 3.1415 和 3141.5 除了小数点的位置不同外,其它都是相同的。可以将第一个数表示为0.31415(基准值)和 10 (缩放因子),而将第二个数表示为0.31415 (基准值相同)和 10000 (缩放因子更大)。缩放因子的作用是移动小数点的位置,术语浮点因此得名。
浮点数可以表示非常大和非常小的数值。
浮点数的书写:
第一种常规表达类似 3.14、0.21 和 -14233.02 这样。
第二种是用 e 或者 E 表示。比如 3.14E6 表示 3.14 与1000000 相乘,-0.12e4 表示 -0.12 与10^4(10000)相乘。因此这类表示方法更适合与表示非常大或者非常小的数值。
2、浮点数的类型
c++ 有 3 种浮点类型:float、double 和 long double。这些类型是按照它们可以表示的有效位数和允许的指数最小范围来描述的。有效位是数字中有意义的位。例如,31.4 有效位数是 3 位,其结果精确到了小数点后一位,而 314000 有效位数同样是 3 位,其结果仅仅精确到了千位,其余的 000只是占位。有效位数不依赖于小数点的位置。
c++ 对有效位数的要求:
folat 至少 32 位,double 至少 48 位,且不少于 float,long double 至少和 double 一样多。这三种类型的有效位数可以一样多。此外,通常说 float 的精度一般为小数点后六位或者七位。如果想要更加深入了解计算机是如何计算浮点数范围和精度的,可以参考这里。
此外,浮点常量通常为 double 类型,如果希望常量为 float 类型,可以使用 f 或 F 后缀,如果希望使用 long double 类型,可以使用 l 或者 L 后缀(更推荐L)。如
3.14f
或者3.14L
。
3、浮点数的优缺点
优点:1、可以表示更多的值;2、可以表示的范围更大。
比如同样为 32 位的 int 和 float 类型,int 能够表示的为 [-2.147483648E9, 2.147483647E9],而float 能够表示 [-3.4028235E38, 3.4028235E38]。
缺点:1、运算速度慢;2、精度降低
由于储存空间为改变,两者皆为 32 位,实际上两者能够储存的数字个数是一样多的(实际上 float 能够储存的更少),但是 float 的范围变大了,这是因为缩放因子的原因,但同样导致了 float 的精度降低,在越远离 0 的远端,精度问题越发明显。详细同样可以参照链接。
4、c++算术运算符
4.1 运算符符号及用法
- +:1 + 2 求和
- - :3 - 2 求差
- * :3 * 2 求积
- / :3/2 求商
- % :3 % 2 求模:生成第一个数除以第二个数后的余数,此处结果为 1。
注意:% 求模符号的数值只能用整数
另外,对于除法运算,如果两个操作数都是整数,那么结果也为整数,结果的小数部分将被丢弃;如果其中一个为浮点数,那么结果为浮点数。
示例程序如下:
// 算术运算符示例程序.cpp--------------
#include <iostream>
int main()
{
using namespace std;
float a = 3.21, b = 2.223;
int c = 5, d = 2;
cout << "a + b =: " << a + b << endl;
cout << "a - b =: " << a - b << endl;
cout << "a * b =: " << a * b << endl;
cout << "a / b =: " << a / b << endl;
cout << "c / d =: " << c / d << endl;
cout << "c % d =: " << c % d << endl;
return 0;
}
4.2 运算符优先级和结合性
- 算术运算符遵循通常的代数优先级,先乘除,后加减;
- 可以用“()”来执行自己定义的优先级;
- 当两个运算符的优先级相同时,c++ 将看操作数的结合性。从左到右的结合性意味着如果两个优先级相同的运算符被同时用于同一个操作数,则首先使用左侧的运算符。从右到左反之。注意:仅当两个运算符都被用于同一个操作数时,优先级和结合性规则才有效。
- 其它符号的优先级以及结合性参考这里。
5、数据类型转换
为了处理潜在的数据混乱,c++ 自动执行很多数据转换:
- 将一种算术类型的值赋给另一种算术类型的变量时,c++ 将对值进行转换;
- 表达式包含不同的类型时,c++ 将对其进行转换;
- 将参数传递给函数时,c++ 将对值进行转换。
以下详细阐明各种转换的方式。
5.1 初始化和赋值进行的转换
c++ 允许将一种类型的值赋给另一种类型的变量。同时,值将被转换为接收变量的类型。比如 a 为 double 类型,b 为 float 类型,执行下列语句:a = b;
这样的语句将 b 的值扩展为 double 类型,即一个新的与 b 相同的值,但为 double 类型的值储存在了 a 中,而 b 的值为改变。
将一个值赋给取值范围更大的类型通常不会导致什么问题,比如将 short 值赋给 long 并不会改变这个值,知识占用更多的字节。但是如果将一个很大的 long 值(如 211111111)赋给 float 变量将降低精度,因为 float 只有 6 位有效数字,这个值将被四舍五入为 2.11111E8。
下表列出了一些可能出现的转换问题:
转换 | 潜在的问题 |
---|---|
将较大的浮点类型转换为较小的浮点类型,比如将 double 转换为 float | 精度(有效位数)降低,值可能出现超出目标类型的取值范围,在这种情况下,结果将是不确定的 |
将浮点类型转换为整型 | 小数部分丢失,原来的值可能超出目标类型的取值范围,在这种情况下,结果将是不确定的 |
将较大的整型转换为较小的整型,如将 long 转换为 short | 原来的值可能超出目标的取值范围。 |
5.2 表达式中的转换
当同一个表达式中包含两种不同的算术类型时,c++ 将执行两种自动转换:首先,一些类型在出现时便会自动转换,其次,有些类型在与其它类型同时出现时将被转换。
1、自动转换类型包括,bool、char、unsigned char、signed char 和short 值,他们将被转换为 int。这类转换被称为整型提升。
示例程序如下:
short a = 10;
short b = 20;
short c = a + b;
为执行第 3 行语句,c++ 先取得 a 和 b 的值,然后将它们转换为 short,最后,程序将结果转换回 short,再赋值给 c,因为声明 c 为 short 类型。计算机进行这类操作是因为 int 使用这中类型时,计算速度最快。
2、当不同类型进行计算时,较小的类型将被转换为较大的类型。比如 9.0 除以 5,因为 9.0 是 double 类型,因此在用 5 除之前,程序将 5 转换为 double 类型。
注意:转换只发生在程序计算过程中。变量的值在计算过程中,为方便计算而进行了类型转换,但是计算结束后,变量的类型并未发生改变。
5.3 强制类型转换
表达式:
(typeName) value;
typeName (value);
// 例如:
float (a); // 将 a 强制转换成 float 类型