运算符
程序里大多数事情都离不开计算:总价、平均分、还剩多少。C++ 的加减乘除写法和数学里差不多,乘号是 *,除号是 /:
1#include <iostream>2 3int main() {4 int apples = 12;5 int pears = 5;6 std::cout << apples + pears << '\n';7 std::cout << apples - pears << '\n';8 std::cout << apples * pears << '\n';9 std::cout << apples / pears << '\n';10 return 0;11}
17 7 60 2
前三行没什么意外。最后一行,12 除以 5 不是 2.4,而是 2。
整数除法和余数
两个 int 相除,结果还是 int:小数部分直接丢掉,不四舍五入。想要被丢掉的那部分,用 % 取余数:
1#include <iostream>2 3int main() {4 int minutes = 135;5 std::cout << minutes / 60 << " 小时\n";6 std::cout << minutes % 60 << " 分钟\n";7 return 0;8}
2 小时 15 分钟
135 分钟里有 2 个完整的 60,剩下 15。% 很常用:n % 2 是 0 就是偶数,n % 10 是最后一位数字。% 只能用在整数上。
8 块披萨分给 3 个人,这段程序显示什么?
1#include <iostream>2 3int main() {4 int slices = 8;5 int people = 3;6 std::cout << slices / people << " " << slices % people << '\n';7 return 0;8}
8 / 3 是整数除法,每人 2 块,小数丢掉;8 % 3 是剩下的 2 块。
static_cast:要小数的结果
求平均数时,整数除法就是个坑:
1#include <iostream>2 3int main() {4 int total = 7;5 int count = 2;6 double wrong = total / count;7 double right = static_cast<double>(total) / count;8 std::cout << wrong << '\n';9 std::cout << right << '\n';10 return 0;11}
3 3.5
wrong 虽然是 double,但 total / count 在放进去之前已经算成了整数 3。static_cast<double>(total) 先把 total 变成 double 7.0,再除,就是小数除法,得到 3.5。只要两边有一个是 double,除法就带小数:写 7.0 / 2 也一样。
小技巧: 你在 C 代码里会看到 (double)total 这种写法,效果一样。C++ 里用 static_cast,它更显眼,也更好搜索。
+= 和 ++
「在原来的基础上加多少」太常见了,所以有简写:stock += 5 就是 stock = stock + 5。-=、*=、/=、%= 也一样。加 1 和减 1 还能更短:++count 和 --count。
1#include <iostream>2 3int main() {4 int stock = 10;5 stock += 5;6 stock -= 3;7 stock *= 2;8 int sold = 0;9 ++sold;10 ++sold;11 std::cout << "库存:" << stock << ",卖出:" << sold << '\n';12 return 0;13}
库存:24,卖出:2
点单步,看 stock 从 10 变成 15、12、24。++ 写在前面(++sold)或后面(sold++)都行,单独一行时效果一样。这门课把它单独写成一行,不放进更长的式子里。
先乘除,后加减
和数学一样,先算 *、/、%,后算 +、-;同一级的从左往右算。拿不准的时候就加括号:
1#include <iostream>2 3int main() {4 int a = 80;5 int b = 90;6 std::cout << a + b / 2 << '\n';7 std::cout << (a + b) / 2 << '\n';8 std::cout << 10 - 4 - 3 << '\n';9 return 0;10}
125 85 3
第一行先算 b / 2 是 45,再加 80,得到 125,不是平均分。加上括号才是 85。10 - 4 - 3 从左往右算,是 3。
这段程序显示什么?
1#include <iostream>2 3int main() {4 std::cout << 2 + 3 * 4 << '\n';5 return 0;6}
先算乘法 3 * 4 是 12,再加 2,得到 14。要先加,就写 (2 + 3) * 4。
int 的上限
int 通常占 4 个字节,能放的数有最大也有最小。<climits> 里的 INT_MAX 和 INT_MIN 就是最大和最小的那两个数。<limits> 里的 std::numeric_limits<int>::max() 和 min() 是另一种写法,换成别的类型也能用:
1#include <iostream>2#include <climits>3#include <limits>4 5int main() {6 std::cout << INT_MAX << '\n';7 std::cout << INT_MIN << '\n';8 std::cout << std::numeric_limits<int>::max() << '\n';9 std::cout << std::numeric_limits<long long>::max() << '\n';10 return 0;11}
2147483647 -2147483648 2147483647 9223372036854775807
int 大约正负 21 亿,第三行和第一行是同一个数;最后一行是 long long 的最大值,大得多。超出这个范围叫溢出。看看最大的数再加 1 会怎样:
1#include <iostream>2#include <climits>3 4int main() {5 int views = INT_MAX;6 std::cout << "现在:" << views << '\n';7 views = views + 1;8 std::cout << "加 1:" << views << '\n';9 return 0;10}
现在:2147483647
signed integer overflow: 2147483647 + 1 cannot be represented in type 'int'发生了什么: 停在第 7 行:2147483647 + 1 超出了 int 的范围(结果放不下)。
int 溢出是未定义行为。在普通的电脑上,它常常悄悄变成一个很大的负数,程序接着跑,错误很难发现。我们的引擎会停在溢出的那一行。数可能很大时(比如世界人口、以分为单位的金额),换成 long long,它能放到大约 9×10¹⁸。
sqrt 和 pow
开平方、乘方这些数学函数在 <cmath> 里。std::sqrt(x) 是平方根,std::pow(x, y) 是 x 的 y 次方,结果都是 double:
1#include <iostream>2#include <cmath>3 4int main() {5 std::cout << std::sqrt(16.0) << '\n';6 std::cout << std::pow(2, 10) << '\n';7 double a = 3;8 double b = 4;9 std::cout << "斜边:" << std::sqrt(a * a + b * b) << '\n';10 return 0;11}
4 1024 斜边:5
C++ 没有乘方运算符:2 ^ 10 能编译,但 ^ 是另一种运算,结果是 8,不是 1024。乘方就用 std::pow,平方直接写 a * a。
练一练
写好代码,点检查。提示随便看,实在想不出来再看答案。
三门课的平均分
✓现在程序显示的是 平均分:89。改一改,让它显示带小数的平均分 平均分:89.6667。
平均分:89.6667
1#include <iostream>2 3int main() {4 int math = 85;5 int english = 90;6 int science = 94;7 int total = math + english + science;8 std::cout << "平均分:" << total / 3 << '\n';9 return 0;10}
分钟换成小时
✓用 / 和 %,把 minutes 换成小时和分钟,显示 200 分钟是 3 小时 20 分钟。
200 分钟是 3 小时 20 分钟
1#include <iostream>2 3int main() {4 int minutes = 200;5 6 return 0;7}
修好它:放不下的步数
✓运行一下:引擎停在了溢出的那一行。改好它,让它显示 4000000000。
4000000000
1#include <iostream>2 3int main() {4 int steps = 2000000000;5 int total = steps + steps;6 std::cout << total << '\n';7 return 0;8}
这一课学会了
+ - * /是加减乘除;两个int相除是整数除法,小数部分丢掉。%是余数,只用于整数:n % 2看奇偶,n % 10取最后一位。static_cast<double>(x)把x变成double,除法就带小数了。x += 5是x = x + 5的简写;++x加 1,--x减 1。- 先乘除后加减,同级从左往右;拿不准就加括号。
int最大是INT_MAX(std::numeric_limits<int>::max()),大约 21 亿;溢出是未定义行为,大数用long long。<cmath>里有std::sqrt和std::pow;^不是乘方。