1. 概念引入:模拟长除法

高精度除法用于计算一个超大整数 AA(超过内置类型范围)除以一个普通整数 bb(在 int 范围内)的商和余数。

其核心原理是完全模拟长除法(竖式除法)的过程

  1. 从高位开始: 从被除数 AA 的最高位开始,依次向低位进行运算。
  2. 累积余数: 在每一步除法中,将上一步的余数乘以 10,再加上当前位的新数字,形成新的被除数。
  3. 求商与新余数: 用这个新被除数除以 bb,得到当前位的商,并计算出新的余数,用于下一位的运算。

2. 实现步骤与代码解析

我们将以您提供的代码为例,分步解析高精度除法的实现。


步骤 A:输入与顺序存储

与加、减、乘法不同,长除法是从高位(左侧)开始计算的,因此我们需要顺序存储大整数 AA 的每一位。

代码解析:

char a[200];
int b;
cin >> a >> b; // 输入大整数 A (字符串) 和除数 b (int)
int lena = strlen(a);

// 将 A 顺序存入 a1,最高位在 a1[1]
for(int i = 0; i < lena; i++)
{
    // a[0] 存入 a1[1], a[1] 存入 a1[2], 以此类推
    a1[i+1] = a[i] - '0'; 
}
// 此时 a1[1] 是 A 的最高位,a1[lena] 是 A 的个位。

步骤 B:核心运算——长除法的模拟

这一步是除法的核心。我们使用一个循环从 AA 的最高位开始遍历,并用一个变量 xx 来存储每一步的余数(即进位到下一位的数值)。

关键变量:

  • x当前累积的余数 (Remainder),初始化为 0。

循环逻辑:

int x = 0; // x 用来存储上一位运算后的余数

for(int i = 1; i <= lena; i++) // 遍历 A 的每一位(从高位到低位)
{
    // 1. 形成新的被除数:上一步余数 * 10 + 当前位数字
    int current_dividend = x * 10 + a1[i];
    
    // 2. 求商:新的被除数 / b
    c[i] = current_dividend / b;
    
    // 3. 更新余数:新的余数是 current_dividend % b,用于下一位的运算
    x = current_dividend % b;
}
  • 特点: 在每一步迭代中,数组 c[i] 存储的是除法结果的第 ii 位商。变量 x 在循环结束后,存储的就是最终的余数

步骤 C:处理前导零与输出结果

商的结果可能会有前导零(例如 123÷4=0303123 \div 4 = 030 \dots 3)。我们需要跳过这些无效的前导零,然后按顺序输出商的每一位。

代码解析:

int lenc = 1;

// 跳过前导零。当 c[lenc] == 0 且还没有到达个位时,lenc++
// 确保如果结果是 0,至少会输出一个 0
while(c[lenc] == 0 && lenc < lena) 
{
    lenc++; 
}

// 顺序输出商的每一位
for(int i = lenc; i <= lena; i++)
{
    cout << c[i];
}
// 最终余数 x 已经被计算出来,但这段代码只输出了商

如何输出余数? 在上述代码的循环结束后,变量 x 中存储的就是最终的余数。如果需要输出余数,可以在 for 循环后添加:cout << endl << x;

3. 完整代码(高精度除法)

#include <bits/stdc++.h>
using namespace std;

int a1[200], c[200]; // a1 存储被除数,c 存储商

int main()
{
	char a[200];
	int b; // 除数 b 是 int 类型
	cin >> a >> b;
	int lena = strlen(a);
	
	// --- 步骤 A: 顺序存储被除数 A ---
	for(int i = 0; i < lena; i++)
	{
		a1[i+1] = a[i] - '0';
	}
	
	// --- 步骤 B: 模拟长除法,计算商和余数 ---
	int x = 0; // 余数 (Remainder)
	
	for(int i = 1; i <= lena; i++)
	{
		// 形成新的被除数
		int current_dividend = x * 10 + a1[i];
		
		// 存储当前位的商
		c[i] = current_dividend / b;
		
		// 更新余数
		x = current_dividend % b;
	}
	
	// --- 步骤 C: 处理前导零与输出 ---
	int lenc = 1;
	
	// 跳过商的前导零,但如果商为 0,至少保留一位
	while(c[lenc] == 0 && lenc < lena)
	{
		lenc++;
	}
	
	// 顺序输出商
	for(int i = lenc; i <= lena; i++)
	{
		cout << c[i];
	}
	
	// 额外输出余数(不在原代码中,但这是高精度除法的重要结果)
	// cout << " R " << x << endl; 
	
	return 0;
}

0 条评论

目前还没有评论...