C++ Prime Plus——第三章 处理数据

本文介绍了C++中的const限定符,浮点数及其优缺点,包括浮点数的书写方式、浮点类型以及浮点数运算的精度问题。此外,还探讨了C++的算数运算符,如除法分支和类型转换,以及类型转换中的精度损失问题。
摘要由CSDN通过智能技术生成

2.const限定符

const关键字用来声明一个常量,常量的名称通常以大写字母开头。

const int Months = 12;

这行代码声明了一个常量Months,并且赋值为12,此后不允许再对常量的值进行修改。因此在声明常量的同时就需要进行赋值

#define也可以完成定义常量的操作,但是const与#define相比的优势在于:

  1. const可以明确常量的类型。
  2. const定义的常量可以限制其作用域,而#define只能定义全局的常量。
  3. const可以用于更复杂的类型的定义。

定义常量时请使用const。

3.浮点数

浮点数能够表示带小数部分的数字,浮点就是因为小数点可以浮动而得名。浮点数可以表示小数、非常大和非常小的数字。浮点数在计算机内部存储的形式与表示的方法与整数有很大的不同。

3.1 书写浮点数

C++中的浮点数有两种书写方式。第一种方式是常用的标准小数点表示法:

  • 12.34
  • 939001.32
  • 0.00023
  • 8.0

即使小数部分为0,小数点也将确保该数字以浮点格式(而不是整数格式)表示。

第二种表示浮点值的方式叫做E表示法:

  • 2.52e+8,在2.52的基础上小数点向右移动8位
  • 8.33E-4,在8.33的基础上小数点向左移动4位

e或E后面的部分是指数,数值代表小数点移动的位数,负数向左移,正数向右移。

image.png

3.2 浮点类型

C++有3种浮点类型:float、double和long 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 tub = 10.0 / 3.0;
	double mint = 10.0 / 3.0;
	const float million = 1.0e6;
	cout << "tub = " << tub;
	cout << ", a million tubs = " << million * tub;
	cout << "\nand ten million tubs = ";
	cout << 10 * million * tub << endl;

	cout << "mint = " << mint << " and a million mints = ";
	cout << million * mint << endl;
	return 0;
}

下面是该程序的输出:
tub = 3.333333, a million tubs = 3333333.250000
and ten million tubs = 33333332.000000
mint = 3.333333 and a million mints = 3333333.333333

可以看到,double类型的精度是远远高于float类型的,在我的系统中float能够精确地表示前7位数字,而7位之后的数字就出现了误差。因此对计算结果的精度要求较高时,尽量选择double类型。上面的程序使用了ostream类种的setf()。迫使输出使用定点数表示法而不是E表示法,并使程序的输出显示到小数点后6位。

3.4 浮点数的优缺点

优点:

  1. 浮点数可以表示整数之间的值
  2. 由于有缩放因子,因此浮点数可表示的范围比整数大很多

缺点:浮点数的运算速度通常比整数运算慢,并且浮点数运算后会丢失精度

#include <iostream>

int main()
{
	using namespace std;
	float a = 2.34E+22f; // 末尾的f表示这是一个float类型的常量,赋值给变量a
	float b = a + 1.0f;
	
	cout << "a = " << a << endl;
	cout << "b - a = " << b - a << endl;
	return 0;
}

下面是该程序的输出:
a = 2.34e+022
b - a = 0

本来b-a的正确结果应该是1,但是由于加1是在第23位上加,而float类型只能够精确地表示前6位或者7位,因此这个修改不会对变量b的数值产生任何影响。

前面说float类型至少有32位,但这里却说float类型只能精确地表示前6位或7位,这不是前后矛盾吗?32位指的是二进制位,后面的6位指的是十进制位。由于单精度浮点数(float)在计算机中存储时有23位尾数(存储的是小数部分的二进制位)和1位始终为1的整数部分(该部分不进行存储),加起来一共24位,而4位二进制数可以完整的表示一个十进制数,因此24位二进制位可以表示6位十进制位,超过这个范围数字就不准确了。由于单精度浮点数尾数占23位,而某些十进制数的小数部分不能用二进制位准确的表示出来(例如0.33),可能会超过23位或者无限循环的情况,存储时自然就会丢失精度。

4.C++算数运算符

C++提供几种算数运算符来完成5种基本的算数运算:加、减、乘、除、取模。

#include <iostream>

int main()
{
	using namespace std;
	float hats, heads;

	cout.setf(ios_base::fixed, ios_base::floatfield);
	cout << "Enter a number: ";
	cin >> hats;
	cout << "Enter another number: ";
	cin >> heads;

	cout << "hats = " << hats << ", heads = " << heads << endl;
	cout << "hats + heads = " << hats + heads << endl;
	cout << "hats - heads = " << hats - heads << endl;
	cout << "hats * heads = " << hats * heads << endl;
	cout << "hats / heads = " << hats / heads << endl;
	return 0;
}

下面是该程序的输出:

Enter a number: 50.25
Enter another number: 11.17
hats = 50.250000, heads = 11.170000
hats + heads = 61.419998
hats - heads = 39.080002
hats * heads = 561.292480
hats / heads = 4.498657

可以看到计算的结果出现了误差,这正是由于一些小数是无法使用二进制精确的表示的,导致尾数很长(尾数只能存23位二进制位),而C++只保证float有6位十进制有效位,当有效位超过6位时数值就不精确了。我想这也正是浮点数常量默认是double类型的原因之一,因此若需要更高的精度,请使用double或者long double

4.1 除法分支

如果参与除法运算的是两个整数,那么C++会进行整除,丢弃小数部分,只保留整数部分。只要其中一个数是浮点数就会保留小数部分。不同类型进行运算时,C++将把它们全部转换为同一类型。

#include <iostream>

int main()
{
	using namespace std;
	cout.setf(ios_base::fixed, ios_base::floatfield);
	cout << "Integer division: 9/5 = " << 9 / 5 << endl;
	cout << "Floating-point division: 9.0/5.0 = " << 9.0 / 5.0 << endl;
	cout << "Mixed division: 9.0/5 = " << 9.0 / 5 << endl;
	cout << "double constants: 1e7/9.0 = ";
	cout << 1e7 / 9.0 << endl;
	cout << "float constants: 1e7f/9.0f = ";
	cout << 1e7f / 9.0f << endl;
	return 0;
}

下面是该程序的输出:

Integer division: 9/5 = 1
Floating-point division: 9.0/5.0 = 1.800000
Mixed division: 9.0/5 = 1.800000
double constants: 1e7/9.0 = 1111111.111111
float constants: 1e7f/9.0f = 1111111.125000

C++重载了除法运算符,是其可以完成3种不同的运算:int除法、float除法、double除法。使用相同符号完成多种不同的操作叫做运算符重载,C++内置了一些重载示例,并且还允许扩展运算符,例如可以允许两个类相加等。

4.2 类型转换

C++发生自动类型转换的情况:

  • 将一种算术类型的值赋给另一种算数类型的变量时,C++将对值进行转换
  • 表达式中包含不同的类型时,C++将对值进行转换
  • 将参数传递给函数时,C++将对值进行转换

低精度会自动转换为高精度,高精度类型转换为低精度类型需要进行强制类型转换,结果可能因为精度丢失而出错;0赋给bool变量时,将被转换为false;非零值将被转换为true。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值