Skip to content

第 4 课:除法和求余 ​

现在蛙蛙想知道买的几种水果的平均价格,但求平均价格需要除法的知识,他在键盘上连除号(÷)这个符号都找不到。氪町博士告诉他,C++ 中的除号与数学中的不一样,是用"/"来表示的。

知道符号是什么后,蛙蛙就急忙计算 3、5、8、10 的平均值,他是这样写的:

cpp
#include <iostream>
using namespace std;
int main()
{
    cout << (3 + 5 + 8 + 10) / 4;
    return 0;
}

在数学中,计算的结果应该是 6.5,但是编译运行后,这个结果是 6。如果四舍五入也应该是 7 才对,但为什么是 6 呢?蛙蛙又陷入了疑惑之中。

于是氪町博士正式开启了除法小课堂,大家跟随蛙蛙一起学习编程中的除法吧!

4.1 整数除法 ​

当两个整数相除时,结果是整数部分,比如:

cpp
#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,再尝试运行一下。

cpp
#include <iostream>
using namespace std;
int main()
{
    int a = 5;
    int b = 0;
    int result = a / b;
    cout << result;
    return 0;
}

编译运行后,发现没有出现任何结果,一段时间后程序结束运行。这是因为除数为 0 会导致程序出现未定义的行为。

4.2 浮点数除法 ​

在除法算式中,如果有一个数是浮点型的,那么除法运算就会得到浮点数的结果,比如:

cpp
#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 / intint
double / intdouble
int / doubledouble
double / doubledouble

也就是说只要除号任意一边出现了浮点数,结果就是浮点数。

只有除号两边都是整数,结果才是整数。

这个规律也适用于加法、减法和乘法。

4.3 实例讲解一 ​

例 1:三人分饼 ​

蛙蛙妈妈早上出去买了 n 块饼作为早餐,准备回家跟蛙蛙爸爸还有蛙蛙平均分了吃,请问每个人能分几块完整的饼?

【输入格式】输入一行,一个正整数 n。

【输出格式】输出一行,为每个人能分得的完整饼数。

【输入样例】10

【输出样例】3

解析

首先我们需要声明一个整型变量 n,然后通过 cin >> n 语句,输入妈妈买饼的总数,比如输入样例中的 10,此时变量 n 的值就被赋值为 10。

然后进行除法运算,除号为"/",这里人数是确定的 3 个人,所以需要使用 n / 3 进行整数除法运算。

由于除号两边均为整数,所以得到的结果会截断小数部分,只取商的整数部分。比如这里的 n 若为 10,10 / 3 得到的结果只取商的整数部分,也就是 3。

参考代码

cpp
#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 就可以了。

参考代码

cpp
#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++ 表示为:

cpp
6 % 5 = 1;  9 % 7 = 2;  9 % 3 = 0;  6 % 10 = 6.

余数注意事项 ​

  1. 求余运算只针对整数类型

只能整数 % 整数,求余符号两边都不能出现浮点数。

  1. 除数不能为 0

在数学定义中,除法是乘法的逆运算。以 a / b = c …… d(d 为余数)为例,如果 b 为 0,除法没有意义,因为任何数乘以 0 都是 0。所以在计算余数之前,也必须保证除数是非 0 的。在 C++ 中,除数为 0 会导致程序出现未定义的行为。

  1. 余数取值范围

余数的取值范围与除数相关,例如除数是 7 时,余数可能的取值有 0、1、2、3、4、5、6。这种情况是由余数的定义决定的,余数是被除数未除尽的部分,所以它一定小于除数。

  1. 较小的数对较大的数取余

对于 a % b,如果 a < b,则结果为 a,比如 3 % 7 的结果为 3。

  1. 别称

求余运算也叫作取模运算。

4.5 实例讲解二 ​

例 3:彩虹糖 ​

蛙蛙买了 n 袋彩虹糖,准备平均分给 4 名同学,多余的留给自己,请问每位同学能分到几袋完整的糖果?蛙蛙自己又能留几袋呢?

【输入格式】输入一行,一个正整数 n,表示蛙蛙买的糖果的袋数。

【输出格式】输出一行,用空格隔开的两个整数,分别表示分给同学的糖果袋数及蛙蛙留下的糖果袋数。

【输入样例】14

【输出样例】3 2

解析

  1. 读取输入:先声明一个整型变量 n,然后通过 cin >> n 语句输入一个正整数,并将输入的值赋给 n,n 代表的是蛙蛙购买的彩虹糖的袋数。比如输入 14,那么变量 n 的值就是 14。

  2. 计算分给同学的完整糖果袋数:直接用整型变量 n / 4 即可得到商的整数部分。例如当 n 等于 14 的时候,14 / 4 得到的结果就是 3,这个结果就是能分到的完整糖果袋数。

  3. 计算蛙蛙留下的糖果袋数:求余运算的符号为 %,若使用正整数 n 对 4 进行求余运算,式子为 n % 4。若 n 为 14,则求余后的结果为 2。

  4. 输出结果:通过 cout 语句进行输出即可,但要注意这里的两个值需要用空格隔开。

参考代码

cpp
#include <iostream>
using namespace std;
int main()
{
    int n;
    cin >> n;
    cout << n / 4 << " " << n % 4;
    return 0;
}

例 4:反转一个三位数 ​

蛙蛙学完除法和求余之后,看着眼前的一个三位数产生了新的想法:他想通过编程将这个三位数反向输出。你觉得通过除法和求余的知识能做到吗?

【输入格式】输入一行,一个三位正整数 n。

【输出格式】输出一行,将这个三位数反向输出。

【输入样例】234

【输出样例】432

解析

若想将一个三位数反向输出,需要先将每个数位上的数字提取出来,再反向输出即可,这里先假设三位数是一个整型变量 n。

  1. 提取各个数位上的数字

百位上的数字提取:使用 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,然后就可以将这个值保存起来。

  1. 反向输出这些数字

我们已经分别获取了 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。

参考代码

cpp
#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;
}

基于 MIT 协议发布