C++复习 第三章 处理数据 第二节

目录

3.2 const 限定符

3.3 浮点数

        3.3.1 书写浮点数

        3.3.2 浮点类型

        3.3.3 浮点常量

        3.3.4 浮点数的优缺点

3.4 C++算数运算符

        3.4.1 类型转换

        1. 初始化和赋值进行的转换

        2. 使用 { } 方式初始化时进行的转换

        3. 表达式中的转换

        4. 传递参数时的转换

        5. 强制类型转换

        3.4.2 C++11中的 auto 声明


3.2 const 限定符

        可以使用 const 修饰变量,被修饰的变量必须在声明时初始化,并且一旦被赋值后,其值就不可以被改变。

//常量 Month 被初始化为12后,其值就被固定了
//编译器将不允许再修改该常量的值
const int Month = 12;

        一种常用的做法是将变量名的首字母大写,以提醒我们这是一个常量,例如上述的 Month 常量。另一种常用的做法是将整个名称全部大写,并且使用 #define 来声明和初始化该常量,例如头文件 <climits> 中的 INT_MAX。

        创建常量的通用格式如下:

//const 常量类型 常量名称 = 常量值;
const type name = value;

//下列代码是不合法的
//因为一旦在声明常量时没有为其赋值
//那么 year 中的值是不确定的,并且无法修改
const int year;
year = 2023;

        const 比 #define 更好用,更灵活,适用范围更广。例如,const 可以初始化类、结构体的值,而 #define 不行。因为后者是预处理语句,只能在未编译文件之前执行。

3.3 浮点数

        浮点数就是小数,能够表示带小数部分的数字。例如,pi ≈ 3.1415926, e ≈ 2.7, c ≈ 299792.458 km/s。计算机将这样的值分成两部分来存储,一部分表式值,另一部分用于对值进行放大和缩小。c ≈ 0.299792458 * 10^6 km/s,这时 c 就被分成了两个部分,0.299792458(基准值)和 1000000(缩放因子)。缩放因子的作用就是移动小数点的位置,所以这种数字叫做浮点数。C++内部表示浮点数的方法与此相同,只不过计算机是基于二进制数,因此缩放因子是 2 的幂,不是 10 的幂。重要的是,浮点数能够表示小数值、非常大和非常小的值,它内部表示方法与整数值有着天壤之别。

        3.3.1 书写浮点数

        C++有两种书写浮点数的方法:

//第一种:标准小数点表示法
-0.98
520.1314
114.514
6.0

//第二种:E表示法(类似于科学计数法,只是将 10^x 换成了 Ex/ex)
-9.8e-1
5.201314e+2
1.14514E+2
6.0E0

        3.3.2 浮点类型

        C++有三种浮点类型:float、double 和 long double。这些类型是按照它们可以表示的有效位数和允许的指数最小范围来描述的。有效位(significant figure)是数字中有意义的位数。例如喜马拉雅山高度为 8848.86m,该数字使用了6个有效位,指出了最接近的高度数。然而,将高度写为 8800m 时,有效位数为 2 位,因为结果四舍五入到了百位,其余两位不过是占位符。当然高度也可以表示为 8.84886km。这样仍然有 6 个有效位数,因为这个值精确到了第六位。

        同样C++对于浮点数也有相应的有效位要求:float 至少32位;double 至少48位,且不少于float;long double 有效位至少和 double 一样多。这三种类型的有效位数可以一样多。然而,通常,float为 32 位,double 为 64 位,long double 为 80、96 或 128 位。另外,这三种类型的指数范围至少是 -37 ~37.

        

#include <iostream>

int main()
{
    using namespace std;
    cout.setf(ios_base::fixed, ios_base::floatfield);
    float a = 10.0 / 3.0;
    double b = 10.0 / 3.0;
    const float million = 1.0e+6;

    cout << "a = " << a << ", a * million = " << a * million << endl;
    cout << "10 * a * million = " << 10 * a * million << endl;
    cout << "b = " << b << ", b * million = " << b * million << endl;
    cout << "10 * b * million = " << 10 * b * million << endl;
    return 0;
}


运行结果:
a = 3.333333, a * million = 3333333.250000
10 * a * million = 33333332.000000
b = 3.333333, b * million = 3333333.333333
10 * b * million = 33333333.333333

         cout 通常会删除浮点数结尾的零。例如 3333333.250000 显示为 3333333.25。而调用 cout.setf() 将覆盖这种行为。值得注意的是 float 的精度比 double 低,就像上述 a 在第八位开始有了误差,但是 b 在显示的所有位数中都是精确的,它显示了13位。系统会确保 float 至少有6位精确,double 至少有15位有效位。

        3.3.3 浮点常量

        在程序中书写浮点常量的时候,程序将把它默认存储为 double 类型。如果希望常量保存为 float 类型,使用 f 或 F 后缀。对于 long double 类型,可使用 l (小写L)或 L 后缀。

1.234f
1.14514E+2F
5.2L

        3.3.4 浮点数的优缺点

        与整数相比,浮点数有两大优点。首先,它们可以表示整数之间的值。其次由于有缩放因子,它们可以表示的范围大得多。最后,浮点数的运算速度通常比整数运算慢,且精度会降低

#include <iostream>

int main()
{
    using namespace std;
    float a = 1.14514E+22f;
    float b = a + 1.0f;
    cout << "a = " << a << endl;
    cout << "b - a = " << b - a << endl;
    return 0;
}


运行结果:
a = 1.14514e+22
b - a = 0

        上述程序的运行结果与实际问题的结果不同,后者的结果理论上应该是 1,但是计算机给出的答案却是 0。这是因为 1.14514e+22 是一个23位的数字,加上一就是在末尾加上1。但是 float 类型只能表示数字中的前 6 位或前 7 位,因此修改第23位将对这个值没有任何影响。

3.4 C++算数运算符

这里先介绍五种基本的C++算数运算符:

        1.  +运算符,对操作数执行加法运算。 24 = 20 + 4

        2.  -运算符,从第一个数中减去第二个数,16 = 20 - 4

        3.  *运算符,将操作数相乘,80 = 20 * 4

        4.  /运算符,用第一个数除第二个数。如果两个数都是整数,那么结果是商的整数部分;如果两个数至少有一个是浮点数,那么结果是正常的商。6 = 20 / 3, 6.666666 = 20 / 3.0

        5.  %运算符求模,用第一个数除第二个数,得到余数。两个数都必须是整数。如果有浮点数,那么将导致编译错误。0 = 20 % 4(如果其中一个数为负数,那么将满足:(a/b)*b + a%b=a)

        3.4.1 类型转换

        C++有11种整型和3种浮点类型,因此计算机在计算时需要处理大量不同的运算情况,尤其是面对不同类型进行运算时。为了处理这种潜在的混乱,C++自动执行很多类型转换:

  • 将一种算数类型的值赋给另一种算术类型的变量时;
  • 表达式中包含不同类型时;
  • 将参数传递给函数时。

        如果不知道进行这些自动转换时将发生的情况,将无法理解一些程序的执行结果,因此下面将详细地介绍这些规则。

        1. 初始化和赋值进行的转换

        C++允许将一种类型的值赋给另一种类型的变量。例如:

int alpha = 1;  //声明一个类型为int的变量
short beta = 2; //声明一个类型为short的变量
alpha = beta;   //将short类型的变量的值赋给int类型变量

        将一个值赋给取值范围更大的类型通常不会导致什么问题,但是将值赋给取值范围更小的类型有可能会出现意外情况(例如降低精度):

int alpha = 5201314; //alpha = 5201314
float beta = alpha;  //beta = 5.20131E+6

double a = 5.201314; //a = 5.201314
int b = a;           //b = 5

//对于零值,将被转化为false;对于非零值,将被转化为true
int cnt = 0;         //cnt = 0
bool n = cnt;        //n = flase
bool m = cnt + 1;    //m = true

        2. 使用 { } 方式初始化时进行的转换

        C++将使用大括号的初始化称为列表初始化(list-initialization),因为这种初始化常用于给复杂的数据类型提供值列表。同时它对数值转换更加严格,集体来说就是,列表初始化不允许缩窄(narrowing),即变量的类型可能无法表示赋给它的值。例如,不可以将浮点类型转化为整型。

const int code = 66;
int x = 66;
char c1 {114514};    //缩窄,不允许
char c2 = {66};      //允许,因为char类型的表示范围包含66
char c3 {code};      //同上
char c4 = {x};       //不允许,因为编译器不知道x的具体值
x = 31325;
char c5 = x;         //允许,但是数值上溢

        3. 表达式中的转换

        当同一个表达式中包含两种不同的算术类型时,C++将执行一些自动转换:首先,一些类型在出现时便会自动转换;其次,有些类型在与其他类型同时出现在表达式中将被转换。例如:

short a = 1;
short b = 2;
short c = a + b;

        在执行上述程序的第三句时:程序先取得 a 和 b 的值,并将它们转化为 int,然后将计算的结果转化为 short 类型,赋值给c。虽然这样可能有些多此一举,但是别忘了 int 是计算机最自然的类型,这意味着计算机使用这些类型的时候,运算速度可能最快。

        还有一些其他的整型提升,如果 short 比 int 短,那么 unsigned short 类型将转化为 int;如果两种类型长度相同,那么 unsigned short 被转化为 unsigned int。还有一些其他规则:

  1. 如果有一个操作数的类型是 long double,则将另一个操作数转化为 long double;
  2. 否则,如果有一个操作数的类型是 double,则将另一个操作数转化为 double;
  3. 否则,如果有一个操作数的类型是 float,则将另一个操作数转化为 floafloat;
  4. 否则,说明所有操作数都是整型,因此执行整型提升。
  5. 在这种情况下,如果两个都是有符号或无符号类型的,且其中一个操作数的级别比另一个低,则转化为级别高的类型。
  6. 如果一个操作数为有符号,另一个操作数为无符号,且无符号操作数级别比有符号级别高,则将有符号操作数转化为无符号操作数所属的类型。
  7. 否则,如果有符号类型可以表示无符号类型的所有可能的取值,则将无符号操作数转化为有符号操作数所属的类型。
  8. 否则,将两个操作数都转化为有符号类型的无符号版本(int => unsigned int)。

        4. 传递参数时的转换

        传递参数时的类型转换通常由C++函数原型控制。然而,也可以取消原型对参数传递的控制,此时,C++将对 char 和 short 类型(signed 和 unsigned)应用整型提升;float 参数提升为double。

        5. 强制类型转换

        C++还允许通过强制类型转换显式地进行类型转换。强制类型转换的格式有两种,例如:

short a = 520;
//将存储在a中的short值转换为int类型
int b = (int) a;
int c = int (a);

        强制类型转换不会改变 a 的类型,而是创建一个新的、指定类型的值,并且可以在表达式中使用这个值。例如:

cout << int('Q') << endl; //显示Q的ASCII值

        还可以使用 static_cast<typeName> (value) 来进行强制类型转换,这将在后面的章节介绍。

        3.4.2 C++11中的 auto 声明

        C++11中增加了一个工具 auto,让编译器能够工具初始值的类型推断变量的类型。在初始化声明中使用关键字 auto,而不指定变量类型,编译器将把变量的类型设置为与初始值相同:

auto cnt = 25; //cnt 为 int 类型
auto alpha = 2.5; //alpha 为 double 类型
auto beta = 2.5e+10L; //beta 为 long double 类型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

♡すぎ♡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值