6-2 算术运算符
一元算术运算符
存在两种一元算术运算符:加号(+)和减号(-)。需要提醒的是,一元运算符是仅接受一个操作数的运算符。
| Operator | Symbol | Form | Operation |
|---|---|---|---|
| Unary plus | + | +x | Value of x |
| Unary minus | - | -x | Negation of x |
一元减unary minus运算符返回操作数乘以-1的结果。换言之,若x=5,则-x等于-5。
一元加unary plus运算符返回操作数的原始值。换言之,+5等于5,+x等于x。通常无需使用此运算符,因其存在冗余性。该运算符主要为与一元减运算符保持对称性而添加。
为提高可读性,这两个运算符都应紧接在操作数之前(例如 -x,而非 - x)。
请勿将一元减运算符与二元减法运算符混淆,它们使用相同的符号。例如在表达式 x = 5 - -3; 中,第一个减号是二元减法运算符,第二个是一元减运算符。
二进制算术运算符
共有5个二进制算术运算符。二进制运算符是指同时接受左操作数和右操作数的运算符。
| Operator | Symbol | Form | Operation |
|---|---|---|---|
| Addition | + | x + y | x plus y |
| Subtraction | - | x - y | x minus y |
| Multiplication | * | x * y | x multiplied by y |
| Division | / | x / y | x divided by y |
| Remainder | % | x % y | The remainder of x divided by y |
加法、减法和乘法运算符与现实生活中的用法完全一致,没有任何特殊限制。
除法和取余运算需要额外说明。除法将在下文讨论,取余运算则留待下一课讲解。
整数与浮点数除法
最简便的理解方式是将除法运算符视为具有两种不同的“模式”。
当任一(或两者)操作数为浮点数Floating point division时,除法运算符执行浮点数除法。浮点除法返回浮点数值,且保留小数部分。例如:7.0 / 4 = 1.75,7 / 4.0 = 1.75,7.0 / 4.0 = 1.75。与所有浮点运算相同,此过程中可能产生舍入误差。
若两个操作数均为整数,则除法运算符执行整数除法。整数除法Integer division舍弃小数部分并返回整数值。例如 7 / 4 = 1(因舍弃小数部分),同理 -7 / 4 = -1(因舍弃小数部分)。
使用static_cast<>对整数进行浮点除法
这引发了一个问题——如果我们有两个整数,想要进行除法运算而不丢失小数部分,该如何实现?
在第4.12节——类型转换与static_cast介绍中,我们展示了如何使用static_cast<>运算符将字符转换为整数,使其以整数形式而非字符形式输出。
同理,我们可使用static_cast<>将整数转换为浮点数,从而实现浮点除法而非整数除法。请看以下代码:
#include <iostream>
int main()
{
constexpr int x{ 7 };
constexpr int y{ 4 };
std::cout << "int / int = " << x / y << '\n';
std::cout << "double / int = " << static_cast<double>(x) / y << '\n';
std::cout << "int / double = " << x / static_cast<double>(y) << '\n';
std::cout << "double / double = " << static_cast<double>(x) / static_cast<double>(y) << '\n';
return 0;
}
这产生了以下结果:

上述内容说明,如果任一操作数是浮点数,则结果将是浮点除法,而非整数除法。
除以 0 和 0.0
当除数为 0 时进行整数除法会导致未定义行为,因为结果在数学上是未定义的!
#include <iostream>
int main()
{
constexpr int apples { 12 };
std::cout << "You have " << apples << " apples. Enter how many people to divide them between: ";
int x {};
std::cin >> x;
std::cout << "Each person gets " << apples / x << " whole apples.\n"; // apples and x are int, so this is integer division
return 0;
}


若运行上述程序并输入0,程序很可能崩溃。尽管尝试,这不会损坏您的计算机。
除以浮点数0.0的结果取决于具体实现(即行为由编译器/架构决定)。在支持IEEE754浮点格式的架构上,结果将为NaN或Inf;在其他架构上,结果很可能导致未定义行为。
相关内容
我们在第4.8节——浮点数中讨论了NaN和Inf。
你可以通过运行以下程序并输入0或0.0来查看程序的运行效果:
#include <iostream>
int main()
{
constexpr int apples { 12 };
std::cout << "You have " << apples << " apples. Enter how many servings of apples you want: ";
double d {};
std::cin >> d;
std::cout << "Each serving is " << apples / d << " apples.\n"; // d is double, so this is floating point division
return 0;
}


算术赋值运算符
| Operator | Symbol | Form | Operation |
|---|---|---|---|
| Addition assignment | += | x += y | Add y to x |
| Subtraction assignment | -= | x -= y | Subtract y from x |
| Multiplication assignment | *= | x *= y | Multiply x by y |
| Division assignment | /= | x /= y | Divide x by y |
| Remainder assignment | %= | x %= y | Put the remainder of x / y in x |
到目前为止,当你需要向变量添加4时,你很可能这样操作:
x = x + 4; // add 4 to existing value of x
这段代码能运行,但略显笨拙,且需要两个运算符才能执行(加法运算符和赋值运算符)。
由于像 x = x + 4 这样的语句非常常见,C++ 为方便起见提供了五个算术赋值运算符。无需编写 x = x + 4,可改写为 x += 4;无需编写 x = x * y,可改写为 x *= y。
因此,上述代码可简化为:
x += 4; // add 4 to existing value of x
修改运算符与非修改运算符
能够修改其操作数值的运算符通常被称为修改运算符modifying operator。在C++中,大多数运算符属于非修改运算符——它们仅使用操作数进行计算并返回结果值。然而,有两类内置运算符既会修改左操作数(同时返回结果值):
- 赋值运算符,包括标准赋值运算符(=)、算术赋值运算符(+=、-=、*=、/=、%=)以及位运算赋值运算符(<<=、>>=、&=、|=、^=)。
- 增量与减量运算符(分别是++和--)。这些将在第6.4节——增量/减量运算符及其副作用中讨论。
列表中未包含的运算符包括==、!=、<=和>=,因其为非修改型关系(比较)运算符(=表示“等于”)。这些将在第6.7节——关系运算符与浮点数比较中讨论。
对于进阶读者
重载运算符可被重新定义为与内置运算符不同的行为,这可能包括修改左操作数(即使内置版本不修改)或反之。例如用于输出的重载operator<<运算符会修改其左操作数(输出流对象)。

浙公网安备 33010602011771号