今天来看一下这个高精度的乘法,之前的是高精度的加法和减法,然后今天的就是乘法和除法,但是这个文章里面主要介绍的还是除法;
还是在这个文章之前声明一下:本篇文章里面的部分图片来自于比特算法课程里面的部分章节,非本人的原创,侵权联系删除,仅供学习交流使用,无任何商业使用行为;
1.高精度乘法的题目
下面的这个就是我们的高精度乘法的具体的题目:其实就是模拟两个数据的乘法,题目是来自于洛谷这个网站
2.模拟计算的过程
下面的这个就是我们模拟的乘法的计算的过程:
1)正常情况下,我们的这个计算的整个流程还是非常的复杂的,例如让大家去计算一下这个三位数和三位数的乘法,其实你也是需要一阵子进行计算的(大部分情况下),而且面对与这样的这个三位数乘以三位数,任何的一次运算可能都会涉及到了这个进位的处理的过程;
因此按照这个正常的方法去进行进位,运算等相关的过程的处理,就会非常的复杂,因此我们引入了下面的这个没有进位的乘法运算,也就是我们的这个运算过程先不去处理这个运算的流程,最后全部计算完毕之后统一进行处理;
2)下面的这个就是老师上课的时候进行的这个具体的运算过程的演示,使用的是三位数乘以三位数进行演示的,也就是我们的123*456乘法的运算的过程;
3)大家可以发现这个运算的过程都是直接把这个结果写到了这个我们的这个过程里面
下面的这个就是我们的高精度运算的过程当中下标的计算规律:大家仔细观察其实应该是可以发现,这个结果的下标呈现出来的这个规律的,例如下面的这个图片里面的210*210的这个题目,210分别对应的就是下标012,另外一个乘数的下标也是这个样子的,例如下面的这个图片的方框圈住的这个2就是我们的第二个乘数的0和我们的第一个乘数的2决定的,也就是第一个乘数的第二个位置的下标和我们的第二个成乘数的第0个小标,也就是2+0得到我们的这个结果的下标,这个就是大致的这个下标的计算的规律;
因此这个下标我们到时候使用这个代码实现的时候就是使用for循环对于ij进行控制,然后结果的这个小标的存放的位置就是我们的两个乘数的i和j相加得到的;
3.代码解释
下面的这个就是我们的高精度乘法的这个模版,还是老样子,我会对于下面的这个代码进行结构的拆分,说明问题;
#include <iostream>
using namespace std;
const int N = 1e6 + 10;
int a[N], b[N], c[N];
int la, lb, lc;
// 高精度乘法的模版 - c = a * b
void mul(int c[], int a[], int b[])
{
// 无进位相乘,然后相加
for(int i = 0; i < la; i++)
{
for(int j = 0; j < lb; j++)
{
c[i + j] += a[i] * b[j];
}
}
// 处理进位
for(int i = 0; i < lc; i++)
{
c[i + 1] += c[i] / 10;
c[i] %= 10;
}
// 处理前导零
while(lc > 1 && c[lc - 1] == 0) lc--;
}
int main()
{
string x, y; cin >> x >> y;
// 1. 拆分每一位,逆序放在数组中
la = x.size(); lb = y.size(); lc = la + lb;
for(int i = 0; i < la; i++) a[la - 1 - i] = x[i] - '0';
for(int i = 0; i < lb; i++) b[lb - 1 - i] = y[i] - '0';
// 2. 模拟乘法的过程
mul(c, a, b); // c = a * b
// 输出结果
for(int i = lc - 1; i >= 0; i--) cout << c[i];
return 0;
}
1)main函数里面的基本是没有太大的这个区别,还是把这个数据存放到我们的这个字符串里面去,这个和高精度的加法和减法是没有任何的这个区别的;
2)模拟乘法的过程就是调用函数,然后这个最后的for循环就是去倒序输出,因为我们当时存放的时候就是倒序进行存放的,我们输出的时候也要记得把这个顺序缓过来,得到这个正确的结果;
3)针对于这个全局的N的定义和我们的三个数组的定义,以及这个字符串的长度的定义,这个都是没有任何的这个区别的;
4)针对于我们的这个mul函数,则是我们的这个高精度乘法这个算法的核心部分,使用的就是我们上面介绍的这个思路,先不处理这个进位的情况,直接把这个得到的结果存放到我们的这个对应的位置上面去,即使这个得到的结果是一个两位数,我们也不需要进行任何的这个处理;
5)其次就是我们的这个下标的存放的位置,这个就是我们上面说过的这个规律,结果的每一个数位的下标就是我们的这个乘数的i,j小标的求和;
6)另外就是这个前导0的处理,这个和大整数的减法里面的这个处理的思路是完全一致的,这个没有任何区别;
7)处理进位这个逻辑也是需要我们去学习一下,可以参考这个上面的笔记,也就是我们从这个低位还是进行这个进位的处理,高位+=我们的结果除以10,低位保留的就是我们的模上10的结果;