第 4 课:除法和求余
现在蛙蛙想知道买的几种水果的平均价格,但求平均价格需要除法的知识,他在键盘上连除号(÷)这个符号都找不到。氪町博士告诉他,C++ 中的除号与数学中的不一样,是用"/"来表示的。
知道符号是什么后,蛙蛙就急忙计算 3、5、8、10 的平均值,他是这样写的:
#include <iostream>
using namespace std;
int main()
{
cout << (3 + 5 + 8 + 10) / 4;
return 0;
}在数学中,计算的结果应该是 6.5,但是编译运行后,这个结果是 6。如果四舍五入也应该是 7 才对,但为什么是 6 呢?蛙蛙又陷入了疑惑之中。
于是氪町博士正式开启了除法小课堂,大家跟随蛙蛙一起学习编程中的除法吧!
4.1 整数除法
当两个整数相除时,结果是整数部分,比如:
#include <iostream>
using namespace std;
int main()
{
int a = 5;
int b = 2;
int result = a / b;
cout << result;
return 0;
}在上述代码中,a/b 的结果为 2,这是因为 C++ 在进行整数除法的时候,会截断小数部分。这下蛙蛙明白了,原来之前的结果里没有小数点后面的数位,也是因为被截断了。
蛙蛙此时还有另一个疑惑:他在数学课上学过除数不能为 0,如果在程序中除数为 0 会出现什么结果呢?
现将 b 的值改为 0,再尝试运行一下。
#include <iostream>
using namespace std;
int main()
{
int a = 5;
int b = 0;
int result = a / b;
cout << result;
return 0;
}编译运行后,发现没有出现任何结果,一段时间后程序结束运行。这是因为除数为 0 会导致程序出现未定义的行为。
4.2 浮点数除法
在除法算式中,如果有一个数是浮点型的,那么除法运算就会得到浮点数的结果,比如:
#include <iostream>
using namespace std;
int main()
{
int a = 5;
double b = 2.0;
double result = a / b;
cout << result;
return 0;
}这里的 a 是整数,b 是双精度浮点数,a/b 的结果为 2.5。出现这种情况的原因是 C++ 会自动将整数 a 转换为浮点数,然后进行浮点数的除法运算。
如果让 a 为浮点数、b 为整数或者 a 和 b 均为浮点数,得到的结果都是一样的。
最后我们总结一下程序中的除法,这里用 int 代表整数、double 代表浮点数,可得出:
| 运算 | 结果 |
|---|---|
| int / int | int |
| double / int | double |
| int / double | double |
| double / double | double |
也就是说只要除号任意一边出现了浮点数,结果就是浮点数。
只有除号两边都是整数,结果才是整数。
这个规律也适用于加法、减法和乘法。
4.3 实例讲解一
例 1:三人分饼
蛙蛙妈妈早上出去买了 n 块饼作为早餐,准备回家跟蛙蛙爸爸还有蛙蛙平均分了吃,请问每个人能分几块完整的饼?
【输入格式】输入一行,一个正整数 n。
【输出格式】输出一行,为每个人能分得的完整饼数。
【输入样例】10
【输出样例】3
解析
首先我们需要声明一个整型变量 n,然后通过 cin >> n 语句,输入妈妈买饼的总数,比如输入样例中的 10,此时变量 n 的值就被赋值为 10。
然后进行除法运算,除号为"/",这里人数是确定的 3 个人,所以需要使用 n / 3 进行整数除法运算。
由于除号两边均为整数,所以得到的结果会截断小数部分,只取商的整数部分。比如这里的 n 若为 10,10 / 3 得到的结果只取商的整数部分,也就是 3。
参考代码
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
cout << n / 3;
return 0;
}例 2:两人分饼
蛙蛙起床发现爸爸妈妈都不在家。当洗漱结束后,妈妈拎着早餐回来了,蛙蛙一问才得知爸爸出差了,这样家里就只有妈妈和蛙蛙两个人了。
妈妈共带回了 n 张饼,这次妈妈准备换个分法:如有需要,可把买来的完整的饼一分为二(即分为 0.5 张饼)。请问这次每个人能分多少块饼?
【输入格式】输入一行,一个正整数 n,表示买的饼的数量。
【输出格式】输出一行,一个数,表示蛙蛙和妈妈分到多少块饼。
【输入样例】5
【输出样例】2.5
【样例说明】输入样例中的 5 表示妈妈买回的饼的数量,输出样例中的 2.5 表示每人分到两张半饼。
解析
题目告诉我们需要声明一个整型变量 n,然后通过 cin >> n 语句,输入妈妈买饼的总数,比如输入样例中的 5,此时变量 n 的值就被赋值为 5。
然后进行除法运算,除号为"/",这里共有 2 个人,所以需要使用 n / 2 进行整数除法运算。但如果这样计算的话,由于除号两边都是整数,所以得到的结果也是整数,跟题目要求不符。
如何才能使得到的结果是浮点数呢?根据之前所学的三种方式,将除号任意一边变成浮点数或者两边都改成浮点数均可。
这里我们将 2 变成浮点数 2.0 就可以了。
参考代码
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
cout << n / 2.0;
return 0;
}你还能想到其他的写法吗?
4.4 余数的定义及注意事项
蛙蛙突然想到之前三人分饼的情况:10 张饼三个人分,每人分 3 张饼,还有一张去哪儿了呢?这一张饼并没有分给任何人,只是剩下了,在数学或者编程中我们称为余数,剩一张饼即余 1 张。
余数的定义
在整数的除法中,只有能整除与不能整除两种情况。
当不能整除时,就会产生余数,余数是指整数除法中被除数未被除尽的部分。
比如刚刚分饼的例子中,10 / 3 很明显不能除尽,剩下的 1 便是余数。用数学公式表示为:被除数 = 除数 × 商 + 余数。在这个例子中,10 = 3 × 3 + 1。
注:原书此处写作"被除数 = 输出 × 商 + 余数",按除法原理应为"被除数 = 除数 × 商 + 余数",疑为排版笔误,此处已修正。
再举一些例子,大家可以将商后面的结果遮住,先自己回答一下结果是什么,比如遮住下方 6 除以 5 后面的结果,自己回答一下商是什么、余数是什么。
- 6 除以 5,商为 1,余数为 1;
- 9 除以 7,商为 1,余数为 2;
- 9 除以 3,商为 3,余数为 0;
- 6 除以 10,商为 0,余数为 6。
在 C++ 中,我们用"%`"来表示求余运算,即求余数。
刚刚的计算用 C++ 表示为:
6 % 5 = 1; 9 % 7 = 2; 9 % 3 = 0; 6 % 10 = 6.余数注意事项
- 求余运算只针对整数类型
只能整数 % 整数,求余符号两边都不能出现浮点数。
- 除数不能为 0
在数学定义中,除法是乘法的逆运算。以 a / b = c …… d(d 为余数)为例,如果 b 为 0,除法没有意义,因为任何数乘以 0 都是 0。所以在计算余数之前,也必须保证除数是非 0 的。在 C++ 中,除数为 0 会导致程序出现未定义的行为。
- 余数取值范围
余数的取值范围与除数相关,例如除数是 7 时,余数可能的取值有 0、1、2、3、4、5、6。这种情况是由余数的定义决定的,余数是被除数未除尽的部分,所以它一定小于除数。
- 较小的数对较大的数取余
对于 a % b,如果 a < b,则结果为 a,比如 3 % 7 的结果为 3。
- 别称
求余运算也叫作取模运算。
4.5 实例讲解二
例 3:彩虹糖
蛙蛙买了 n 袋彩虹糖,准备平均分给 4 名同学,多余的留给自己,请问每位同学能分到几袋完整的糖果?蛙蛙自己又能留几袋呢?
【输入格式】输入一行,一个正整数 n,表示蛙蛙买的糖果的袋数。
【输出格式】输出一行,用空格隔开的两个整数,分别表示分给同学的糖果袋数及蛙蛙留下的糖果袋数。
【输入样例】14
【输出样例】3 2
解析
读取输入:先声明一个整型变量 n,然后通过
cin >> n语句输入一个正整数,并将输入的值赋给 n,n 代表的是蛙蛙购买的彩虹糖的袋数。比如输入 14,那么变量 n 的值就是 14。计算分给同学的完整糖果袋数:直接用整型变量 n / 4 即可得到商的整数部分。例如当 n 等于 14 的时候,14 / 4 得到的结果就是 3,这个结果就是能分到的完整糖果袋数。
计算蛙蛙留下的糖果袋数:求余运算的符号为 %,若使用正整数 n 对 4 进行求余运算,式子为 n % 4。若 n 为 14,则求余后的结果为 2。
输出结果:通过 cout 语句进行输出即可,但要注意这里的两个值需要用空格隔开。
参考代码
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
cout << n / 4 << " " << n % 4;
return 0;
}例 4:反转一个三位数
蛙蛙学完除法和求余之后,看着眼前的一个三位数产生了新的想法:他想通过编程将这个三位数反向输出。你觉得通过除法和求余的知识能做到吗?
【输入格式】输入一行,一个三位正整数 n。
【输出格式】输出一行,将这个三位数反向输出。
【输入样例】234
【输出样例】432
解析
若想将一个三位数反向输出,需要先将每个数位上的数字提取出来,再反向输出即可,这里先假设三位数是一个整型变量 n。
- 提取各个数位上的数字
百位上的数字提取:使用 n / 100 进行除法运算,两个整数相除得到的结果也是整数,所以只会保留 n 的百位。例如当 n 等于 234 时,234 / 100 的结果为 2,然后保存一下这个值。
十位上的数字提取:先用 n / 10,再将除后的结果对 10 取余即可得到十位上的数字。例如当 n 等于 234 时,234 / 10 的结果为 23,然后再将 23 对 10 取余,得到的结果为 3,最后再保存一下这个值。
个位上的数字提取:使用 n % 10 进行求余运算即可,因为一个整数对 10 求余,得到的余数就是这个数的个位数字。例如当 n 等于 234 时,234 % 10 的结果为 4,然后就可以将这个值保存起来。
- 反向输出这些数字
我们已经分别获取了 n 的百位、十位、个位上的数字,原来的排列是百、十、个,现在改为个、十、百即为其反向输出的结果。
但是这样会出现一些问题,比如当我们输入 230 时,反向输出的结果为 032,但实际上最高位的 0 应该去掉。所以我们可以这样输出:将原来个位上的数字乘 100 + 原来十位上的数字乘 10 + 原来百位上的数字。例如当 n 等于 234 时,我们现在分别获取了 2、3、4,输出的内容为 4 * 100 + 3 * 10 + 2 的结果,即为 432。若 n 为 230,那么输出为 0 * 100 + 3 * 10 + 2 的结果,即为 32。
参考代码
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int hundred = n / 100; // 提取百位上的数字
int ten = n / 10 % 10; // 提取十位上的数字
int unit = n % 10; // 提取个位上的数字
cout << unit * 100 + ten * 10 + hundred;
return 0;
}