CC++ & Algorithm

带余除法

中等12
语言版本:通用
概述:从分苹果剩几个的生活场景引出带余除法公式,解释商和余数的唯一性,并展示C++和Python中如何用除法和取模运算得到商和余数。

带余除法:分苹果里的数学秘密

你有没有遇到过这样的情况:妈妈买来23个苹果,家里有4个人,每人分5个,还剩下3个。怎么用数学把“分不完”这个过程写清楚呢?这就是带余除法要做的事——它专门研究“分东西,总有剩余”的情况。带余除法不仅在分苹果时有用,还能帮我们推算星期几、判断奇偶、甚至设计游戏里的循环事件。下面我们就从生活出发,一步步揭开它的秘密。


1. 生活中的带余除法

带余除法其实每天都在发生。比如:

  • 分零食:你有27块巧克力,想分给5个朋友,每人5块,剩下2块;如果分给6个朋友,每人4块,剩下3块。巧克力总是分不完,除非总块数是人数的整数倍。
  • 零花钱:你每周有10元零花钱,想存钱买一个35元的玩具,需要多少周?10÷35不够除,但可以用带余除法表示:35 = 10×3 + 5,意思是存3周得30元,还差5元。
  • 排队:学校操场上,同学们按每排7人站队。如果总共有50人,能站满多少排?50÷7=7排余1人,那多余的一人需要单独站一列。
  • 星期推算:今天是星期三,再过10天是星期几?10÷7=1余3,星期三加3天是星期六。这里用到了“周期”和“余数”。

生活中到处都可以见到带余除法的影子:分东西、循环事件、时间间隔……它帮我们处理“分不完”或“循环周期”的问题。


2. 带余除法的数学公式

带余除法有一个非常重要的定理,叫做带余除法定理

给定两个整数 aabbb0b \neq 0),存在唯一的一对整数 qq (商)和 rr (余数),使得:

a=b×q+ra = b \times q + r

并且满足 0r<b0 \le r < |b|

这里:

  • aa 是被除数(总数)
  • bb 是除数(每份的大小或人数)
  • qq 是商(能分多少份)
  • rr 是余数(还剩多少)

比如 23 ÷ 4:

  • a=23a = 23b=4b = 4
  • q=5q = 5,因为 4×5=204\times5=20,剩下3
  • r=3r = 3,且 03<40\le3<4 成立
  • 验证:4×5+3=20+3=234\times5+3=20+3=23

唯一性:商和余数是唯一的。比如 23 ÷ 4,你不能说“商是4,余数是7”,因为 7≥4,余数不能大于等于除数。同样也不能说“商是6,余数是-1”,因为余数必须是非负数。

? 小提示:当余数 r=0r=0 时,就是整除,比如 12 ÷ 4 = 3 余0,我们说4整除12。


3. 如何求商和余数?——两种方法

方法一:循环减法(理解本质)

从被除数中不断减去除数,直到剩下的数小于除数。减的次数就是商,最后剩下的数就是余数。

例如 23 ÷ 4:

  • 23 - 4 = 19 (第1次)
  • 19 - 4 = 15 (第2次)
  • 15 - 4 = 11 (第3次)
  • 11 - 4 = 7 (第4次)
  • 7 - 4 = 3 (第5次)
  • 3 小于 4 了,停止。
  • 减了5次 → 商=5,剩下3 → 余数=3。

这个方法很直观,但数字很大时效率低。编程中一般用除法运算符。

方法二:除法+取模(编程常用)
  • 求商:用整数除法。在C++中,正整数除法 a / b 直接丢掉小数部分(截断)。在Python中,用 a // b(向下取整)。对于正整数,结果一样。
  • 求余数:用取模运算符 %,得到 a % b

例如 23 ÷ 4:

  • 商 = 23 / 4 = 5(C++)或 23 // 4 = 5(Python)
  • 余数 = 23 % 4 = 3

4. 编程实现:C++ 和 Python 中的带余除法

下面是两个完整的程序,让你输入苹果数和人数,自动算出每人分几个、还剩几个,并验证公式。

C++ 代码
#include <iostream>
using namespace std;

int main() {
    int total, people;  // total: 苹果总数, people: 人数
    cout << "请输入苹果总数和人数(正整数,用空格分隔):";
    cin >> total >> people;
    
    if (people == 0) {  // 除数不能为0
        cout << "人数不能为0!" << endl;
        return 1;
    }
    
    int each = total / people;   // 每人分到的苹果数(商)
    int left = total % people;   // 剩余的苹果数(余数)
    
    cout << total << "个苹果分给" << people << "人,每人" 
         << each << "个,还剩" << left << "个。" << endl;
    
    // 验证公式:total == people * each + left
    int check = people * each + left;
    if (check == total) {
        cout << "验证正确:" << people << "*" << each << " + " << left 
             << " = " << check << " == " << total << endl;
    } else {
        cout << "验证失败,请检查代码!" << endl;
    }
    
    // 循环减法演示(仅用于教学,实际不用)
    int temp = total;   // 临时变量,存放剩余苹果
    int count = 0;      // 记录减了多少次
    while (temp >= people) {
        temp -= people;
        count++;
    }
    cout << "(循环减法:总共减了" << count << "次,剩余" << temp << "个)" << endl;
    
    return 0;
}

运行示例

请输入苹果总数和人数(正整数,用空格分隔):23 4
23个苹果分给4人,每人5个,还剩3个。
验证正确:4*5 + 3 = 23 == 23
(循环减法:总共减了5次,剩余3个)
Python 代码
total = int(input("请输入苹果总数(正整数):"))  # 苹果总数
people = int(input("请输入人数(正整数):"))     # 人数

if people == 0:  # 除数不能为0
    print("人数不能为0!")
else:
    each = total // people   # 每人分到的苹果数(商)
    left = total % people    # 剩余的苹果数(余数)
    
    print(f"{total}个苹果分给{people}人,每人{each}个,还剩{left}个。")
    
    # 验证公式
    check = people * each + left
    if check == total:
        print(f"验证正确:{people}*{each} + {left} = {check} == {total}")
    else:
        print("验证失败,请检查代码!")
    
    # 循环减法演示
    temp = total  # 临时变量
    count = 0     # 计数
    while temp >= people:
        temp -= people
        count += 1
    print(f"(循环减法:总共减了{count}次,剩余{temp}个)")

运行示例

请输入苹果总数(正整数):23
请输入人数(正整数):4
23个苹果分给4人,每人5个,还剩3个。
验证正确:4*5 + 3 = 23 == 23
(循环减法:总共减了5次,剩余3个)

5. 新手常犯的错误

  1. 除数为0:任何数除以0都没有意义,程序会崩溃或报错。一定要先检查除数是否为0。
  2. 余数大于等于除数:比如 23 ÷ 4 余数等于7?不对!余数必须小于除数(0 ≤ r < |b|)。如果算出来余数≥除数,说明还可以继续分,商算少了。
  3. 混淆商和余数:有同学会把商当成“每人分几个”,余数当成“还剩几个”,但要记住:商是分到的整数份数,余数是剩下的零头。
  4. 负数处理误解:如果被除数或除数是负数,不同编程语言的处理可能不同。C++ 中 % 的结果符号与被除数相同(比如 -23 % 4 = -3),而 Python 中 % 的结果永远是非负的(-23 % 4 = 1)。这个话题稍复杂,我们先学好正数情况,之后在“负数取模”知识点中再深入。
  5. 循环减法时忘记更新退出条件:如果 while 循环条件写成了 temp > 0,会陷入死循环,因为一直减下去可能永远不停止(除非正好整除)。必须用 temp >= b 判断。

6. 完整示例:模拟“分糖果”过程

下面是一个综合示例,让你输入糖果总数、每包糖果的颗数,输出能装满多少包,还剩多少颗,并用带余除法验证。

C++ 版本

#include <iostream>
using namespace std;

int main() {
    int candy, per_pack;  // candy: 糖果总数, per_pack: 每包装的颗数
    cout << "请输入糖果总数和每包糖果颗数(正整数,空格分隔):";
    cin >> candy >> per_pack;
    
    if (per_pack == 0) {
        cout << "每包颗数不能为0!" << endl;
        return 1;
    }
    
    int packs = candy / per_pack;   // 能装满的包数(商)
    int leftover = candy % per_pack; // 剩下的糖果(余数)
    
    cout << candy << "颗糖果可以装满" << packs << "包," 
         << "还剩" << leftover << "颗。" << endl;
    
    // 验证:糖果总数 == 包数 * 每包颗数 + 剩余
    int check = packs * per_pack + leftover;
    if (check == candy) {
        cout << "验证正确!" << endl;
    } else {
        cout << "验证失败,请检查!" << endl;
    }
    return 0;
}

Python 版本

candy = int(input("请输入糖果总数(正整数):"))  # 糖果总数
per_pack = int(input("请输入每包糖果颗数(正整数):"))  # 每包颗数

if per_pack == 0:
    print("每包颗数不能为0!")
else:
    packs = candy // per_pack   # 包数(商)
    leftover = candy % per_pack # 剩余颗数(余数)
    print(f"{candy}颗糖果可以装满{packs}包,还剩{leftover}颗。")
    
    check = packs * per_pack + leftover
    if check == candy:
        print("验证正确!")
    else:
        print("验证失败,请检查!")

7. 带余除法的更多应用

带余除法不只是分东西,它在数学和编程中用处广泛:

  • 奇偶判断:一个数除以2,余数为0是偶数,余数为1是奇数。代码:if (num % 2 == 0) // 偶数
  • 周期性任务:比如在游戏中,每5秒发射一颗子弹,当前时间t秒,t除以5的余数可以知道距离下次发射还有几秒。
  • 进制转换:把十进制数转为二进制,不断除以2取余数,就是不断在用带余除法。
  • 日期计算:判断某年是否是闰年?如果年份能被4整除但不能被100整除,或者能被400整除,就是闰年——这背后也是带余除法。

8. 接下来可以学什么?

掌握带余除法之后,你可以继续探索:

  • 整除与因数:如果余数为0,我们就说除数能整除被除数,此时除数是因数。比如12 ÷ 3 = 4 余0,3是12的因数。
  • 同余概念:两个数除以同一个除数得到的余数相同,就说它们模这个除数同余。比如23和7除以4的余数都是3,所以23≡7 (mod 4)。这在密码学和时钟问题里非常重要。
  • 最大公约数与最小公倍数:可以用带余除法(辗转相除法)高效求两个数的最大公约数。
  • 负数取模的陷阱:理解C++和Python中负数的余数为什么不同,以及如何在编程中正确处理。

把这些都搞懂,你的数学和编程能力会更上一层楼!

例题精讲

1单选题

在带余除法中,被除数 = 除数 × 商 + 余数,其中余数的正确取值范围是什么?

A0 ≤ 余数 < 除数
B0 < 余数 ≤ 除数
C0 ≤ 余数 ≤ 除数
D余数可以大于或等于除数
2判断题

对于任意给定的整数被除数a(a≥0)和正整数除数b,带余除法的商和余数是唯一确定的。

3单选题

在Python中,表达式 13 % 4 的结果是多少?

A3
B1
C0
D2
4判断题

在C++中,表达式 (-7) % 3 的结果是 2。

5填空题
以下Python函数用于计算两个正整数相除的商和余数,请补全代码。

def division(a, b):
    quotient = a // b
    remainder = a ___ b
    return quotient, remainder