本课时有配套视频讲解,购买后即可观看(永久有效)
高精度除运算
一、课上练习
编程练习
- 高精度除运算:L3041
二、知识总结
✨ 核心思想
高精度运算是指在计算机科学和数值计算中,能够处理和运算非常大的数字的技术。在编程中,普通的整数类型(如 int 或 long)有其最大值的限制,超过这个范围的运算就会溢出。为了处理更大的数字,比如在大数加密、科学计算或经济模型分析中,就需要用到高精度(大数)运算。
高精度除运算模拟的是手算长除法的过程。与加、减、乘运算从低位开始不同,除法需要从最高位开始逐位计算商,同时维护一个余数。这里实现的是高精度数除以普通整数的情况。
✨ 算法原理
高精度除法的实现步骤如下:
- 字符串存储:使用
string类变量来存储整个大数,字符串的每个字符可以直接映射到每一位上的数字。 - 逆序存入数组:将每一位上的数字逆序存储进数组中,便于统一处理。
- 从高位到低位逐位求商:从最高位开始,将当前余数乘以 10 加上当前位的数字,然后除以除数得到该位的商,取模得到新的余数。这个过程与手算长除法完全一致。
- 清除前导零并输出:清除前导零,逆序输出按位除的结果。
✨ 代码实现
以下是高精度除法(大数除以普通整数)的完整实现:
高精度除运算代码示例
1#include <iostream>
2using namespace std;
3
4// 将字符串s中的数字倒序转换为整数数组a
5void convert(int a[], string s) {
6 int len = s.length(); // 获取字符串长度
7 for (int i = 0; i < len; i++) {
8 a[i] = s[len - 1 - i] - '0'; // 倒序存储,便于从最高位开始运算
9 }
10}
11
12// 打印整数数组a表示的数字,数组中数字是倒序存储的
13void print(int a[], int len) {
14 for (int i = 0; i < len; i++) {
15 cout << a[len - 1 - i]; // 从后向前打印数组元素,以正确顺序显示数字
16 }
17 cout << endl;
18}
19
20// 执行高精度除法运算
21void division(int a1[], int len1, int a2, int result[], int &len) {
22 int remainder = 0; // 初始化余数
23 for (int i = len1 - 1; i >= 0; i--) {
24 remainder = remainder * 10 + a1[i]; // 将余数乘以基数10并加上当前位的数字
25 result[i] = remainder / a2; // 计算当前位的商
26 remainder %= a2; // 更新余数
27 }
28 while (result[len - 1] == 0 && len > 1) { // 清除结果前导0,但至少保留一位数字
29 len--;
30 }
31}
32
33int main() {
34 string s1;
35 int a1[105] = {0}; // 存储数字的数组,初始化为0
36 int a2 = 0; // 存储除数
37 cin >> s1 >> a2; // 读取被除数和除数
38 int len1 = s1.length(); // 获取被除数的长度
39 convert(a1, s1); // 转换被除数为整数数组
40
41 int result[105] = {0}; // 存储结果的数组,初始化为0
42 int len = len1; // 设置结果长度初值为被除数的长度
43
44 division(a1, len1, a2, result, len); // 执行除法运算
45
46 print(result, len); // 打印结果
47 return 0;
48}✨ 执行示例
以计算 1573 ÷ 6 为例:
第一步:逆序存入数组
- a1[] = {3, 7, 5, 1}(对应 1573 的个位3、十位7、百位5、千位1)
- a2 = 6(普通整数除数)
- len1 = 4
第二步:从高位到低位逐位求商(从 i=3 到 i=0)
| 步骤 | 位置i | remainder×10+a1[i] | result[i]=余数÷6 | 新remainder=余数%6 |
|---|---|---|---|---|
| 1 | 3(千位) | 0×10+1=1 | 1÷6=0 | 1%6=1 |
| 2 | 2(百位) | 1×10+5=15 | 15÷6=2 | 15%6=3 |
| 3 | 1(十位) | 3×10+7=37 | 37÷6=6 | 37%6=1 |
| 4 | 0(个位) | 1×10+3=13 | 13÷6=2 | 13%6=1 |
result[] = {2, 6, 2, 0},余数 = 1
第三步:清除前导零
- result[3] = 0,len 从 4 减为 3。
- result[2] = 2 不为零,停止清除。
第四步:逆序输出
- 从 result[2] 到 result[0],输出
262
验证:1573 ÷ 6 = 262 余 1,正确。
注意这个过程与手算长除法完全一致:
10 2 6 2
2 --------
36 | 1 5 7 3
40 → 1÷6=0 余 1
5 1 2 → 15÷6=2 余 3
6 3 6 → 37÷6=6 余 1
7 1 2 → 13÷6=2 余 1✨ 解题步骤详解
当你遇到一道高精度除法题时,可以按以下步骤思考:
- 确认除法类型:本节学习的是"大数除以小数"(高精度数除以普通整数)。如果是"大数除以大数",需要更复杂的算法。
- 读入数据:被除数用
string读入,除数用int读入。 - 逆序存入数组:被除数的每位逆序存入数组。
- 从高位开始计算:与加减乘从低位开始不同,除法从最高位开始。维护一个
remainder变量,每次将remainder * 10 + 当前位作为当前被除数。 - 求商和余数:当前位的商 = 当前被除数 / 除数,新的余数 = 当前被除数 % 除数。
- 清除前导零:商的高位可能为 0(如上例千位为 0),需要清除。
- 输出结果:逆序输出商,如果需要余数也可以单独输出。
✨ 常见错误
- 方向搞反:高精度加、减、乘都从低位(下标 0)开始运算,但除法从高位(下标 len-1)开始。这是初学者最容易混淆的地方。
- 余数没有正确传递:每一步的余数必须乘以 10 再加上下一位的数字,如果忘记乘 10,结果会完全错误。
- 除数为 0 未处理:实际编程中应检查除数是否为 0,避免运行时错误。
- 前导零处理不当:例如
6 ÷ 12,商为 0,如果前导零清除过度会导致无输出。要保证至少保留一位。 - 结果长度设置错误:高精度除法的结果长度初始值应该等于被除数的位数(不像乘法那样是两个长度之和),然后通过清除前导零来缩短。
三、课后练习
编程练习
- 除以13:L3042