
一高精度乘法计算
【输入】输入两行,第一行输入a,第二行输入b。
【输出】输出一行,a*b的积。
(在计算高精度加法之前,先回忆一下竖式乘法的计算过程,此处略过)
【高精度乘法 - 计算过程】
1、准备工作:
使用字符串类型变量存储a、b两个乘数,创建一维整型数组A、B、C、SUM,使用A、B存储乘数a、乘数b的数位,使用C存储每个数位的乘积,使用SUM累加每次C的结果。
2、预处理:
将a、b的字符串长度分别存入数组A、B的0号元素里,然后分离出字符串中的每个数字,并分别倒序存入A、B数组中。
3、模拟竖式计算:
依次取出B中的每个数位,与A中的每个数位相乘,将结果存入C中,然后将C累加到SUM中。注意:B中数位每向高移动一位,与A相乘的结果C的末尾就要多加一个0。
4、输出结果:
倒序输出数组SUM的每个数位。
以上就是高精度乘法的具体计算步骤。
【高精度乘法 - 示例程序】常规算法
- # include <bits/stdc++.h>
- using namespace std;
- // 声明数组A、B,存储两个乘数的数位
- int A[101], B[101];
- // 数组C存储B中数位与A的乘积(注意长度翻倍)
- int C[202];
- // 每次得出C,将C累加到SUM中(注意长度与初始值)
- int SUM[202] = {1};
- // 预处理:记录数位、分离数字、倒序存储
- void fen_li(string s, int a[]) {
- // 将字符串长度存入数组的0号元素里
- a[0] = s.size();
- // 从字符串中分离出数字,倒序存入数组中
- for (int i = 1; i <= a[0]; i++) a[i] = s[a[0]-i] - '0';
- return;
- }
- //声明加法运算函数(将C累加到SUM中)
- void big_plus(int C[], int SUM[]) {
- SUM[0] = max(C[0], SUM[0]); // SUM[0]存储加数的最高数位
- int j = 0; // 声明变量j存储进位数字,默认为0
- for (int i = 1; i <= SUM[0]; i++) {
- SUM[i] += C[i] + j; // 计算当前数位两个加数与进位之和
- j = SUM[i] / 10; // 先计算新的进位
- SUM[i] %= 10; // 再处理结果(和)的当前数位
- }
- if (j > 0) { // 如果最后的进位数字大于0
- SUM[0]++; // 结果的数位加1
- SUM[SUM[0]] = j; // 结果的最高数位设为进位数字
- }
- return;
- }
- // 声明乘法运算函数(B中第n数位与A相乘)
- void big_multiply(int n, int A[]) {
- // 初始化数组C(所有元素设为0)
- for (int i = 0; i < 202; i++) C[i] = 0;
- C[0] = A[0] + n - 1; // 设定当前乘积的数位
- int j = 0; // 进位默认为0
- for (int i = 1; i <= A[0]; i++) { // 遍历A中每一位
- C[i+n-1] = B[n] * A[i] + j; // 计算B[n]与A[i]的乘积再加进位数
- j = C[i+n-1] / 10; // 计算进位数
- C[i+n-1] %= 10; // 计算当前数位
- }
- if (j > 0) { // 如果最后的进位大于0
- C[0]++; // 结果的数位加1
- C[C[0]] = j; // 结果的最高数位这位进位数字
- }
- return;
- }
- int main() {
- string a, b;
- cin >> a >> b; // 输入高精度乘数a、b的值
- fen_li(a, A); // 字符串预处理
- fen_li(b, B);
- for (int i = 1; i <= B[0]; i++) { // 遍历B中的每个数位
- big_multiply(i, A); // 将当前遍历到的数与A相乘
- big_plus(C, SUM); // 将乘积C累加到SUM中
- }
- for (int i = SUM[0]; i > 0; i--) {
- cout << SUM[i]; // 倒序输出SUM中的数位
- }
- cout << endl;
- return 0;
- }

c[i+j-1] = a[i] * b[j] + c[i+j-1] + jw
【高精度乘法 - 示例程序】解析算法
- # include <bits/stdc++.h>
- using namespace std;
- string a, b; // 声明字符串变量a、b存储两个乘数
- int A[101], B[101]; // 声明数组A、B,存储两个乘数的数位
- int C[202]; // 数组C存储B中数位与A的乘积(注意长度翻倍)
- void fen_li(string s, int a[]) { // 预处理
- a[0] = s.size(); // 记录数位、分离数字、倒序存储
- for (int i = 1; i <= a[0]; i++) a[i] = s[a[0]-i] - '0';
- return;
- }
- // 声明乘法运算函数:解析算法(A与B相乘,结果存入到C中)
- void big_multiply() {
- C[0] = A[0] + B[0]; // 设定乘积的数位
- int jw; // 声明进位变量
- for (int i = 1; i <= B[0]; i++) { // 遍历B中每一位数字
- jw = 0; // 每轮内循环开启之前,进位值默认设为0
- for (int j = 1; j <= A[0]; j++) { // 遍历A中每一位数字
- C[i+j-1] += A[j] * B[i] + jw; // 根据解析公式计算C中数位
- jw = C[i+j-1] / 10; // 计算本次的进位值
- C[i+j-1] %= 10; // 计算当前数位
- }
- C[i+A[0]] = jw; // 无论进位值是否为0,最后都存储一次进位值
- }
- while (C[C[0]] == 0 && C[0] > 1) C[0]--; // 清空前导0
- return;
- }
- int main() {
- cin >> a >> b; // 输入高精度乘数a、b的值
- fen_li(a, A); // 字符串预处理
- fen_li(b, B);
- big_multiply(); // 调用公式执行计算
- // 倒序输出C中的每个数位
- for (int i = C[0]; i > 0; i--) cout << C[i];
- cout << endl;
- return 0;
- }
二高精度除法计算
近年比赛从来没考过高精度除法,原理都一样。掌握加、减、乘法运算,熟练之后,自然也能写出高精度除法的代码。
题目 1:
输入一个整数n(n<=5000),求n的阶乘。
【参考代码】5000以内的阶乘
- #include <bits/stdc++.h>
- using namespace std;
- // 求5000以内的阶乘(低精度与高精度相乘)
- int ret[100000]; // 使用数组存储结果 ret,默认为10万位
- int n, k, jw; // n为输入数字,k为结果的数位个数,jw表示进位值
- int main() {
- k = 1;
- ret[1] = 1;
- cin >> n;
- // 特殊情况处理
- if (n < 0) cout << "输入有误" << endl;
- if (n < 2) cout << 1 << endl;
- // 循环2~n之间的每个数,分别与ret相乘(低精度乘以高精度)
- for (int i = 2; i <= n; i++) {
- jw = 0; // 每轮内层循环开启之前,都要将进位重置为0
- for (int j = 1; j <= k; j++) { // 遍历ret的每个数位
- int tmp = ret[j] * i + jw; // 将相乘之积与进位之和存入tmp临时变量中
- jw = tmp / 10; // 计算当前进位值
- ret[j] = tmp % 10; // 计算当前结果数位
- }
- while (jw > 0) { // 每次内层循环结束之后,只要进位值大于0
- k++; // 就将数位个数加1
- ret[k] = jw % 10; // 将第k为数字设为进位的末位数字
- jw /= 10; // 去除进位值的末位数字
- }
- }
- // 输出结果:倒序输出数组ret中的元素
- for (int i = k; i > 0; i--) cout << ret[i];
- cout << endl;
- return 0;
- }
题目 2:
输入a、b两个正整数,计算 a ^ b。(0<a<10000, 0<b<200)
【参考代码】计算 a ^ b
- #include <bits/stdc++.h>
- using namespace std;
- // 求a^b(a、b均为低精度),低精度与高精度的乘法
- int ret[100000]; // 使用数组存储结果 ret,默认为10万位
- int a, b, k, jw; // a、b为输入数字,k为结果的数位个数,jw表示进位值
- int main() {
- k = 1; // 默认数位为 1
- ret[1] = 1; // 第一位的数位值为 1
- cin >> a >> b; // 输入a、b、的值
- // 特殊情况处理
- if (b < 0)
- cout << "输入有误" << endl;
- // 循环b次,分别与ret相乘(低精度乘以高精度)
- for (int i = 1; i <= b; i++) {
- jw = 0; // 每轮内层循环开启之前,都要将进位重置为0
- for (int j = 1; j <= k; j++) { // 遍历ret的每个数位
- int tmp = ret[j] * a + jw; // 将相乘之积与进位之和存入tmp临时变量中
- jw = tmp / 10; // 计算当前进位值
- ret[j] = tmp % 10; // 计算当前结果数位
- }
- while (jw > 0) { // 每次内层循环结束之后,只要进位值大于0
- k++; // 就将数位个数加1
- ret[k] = jw % 10; // 将第k为数字设为进位的末位数字
- jw /= 10; // 去除进位值的末位数字
- }
- }
- // 输出结果:倒序输出数组ret中的元素
- for (int i = k; i > 0; i--) cout << ret[i];
- cout << endl;
- return 0;
- }