目录
1.前言
因为本人也需要学习高精度乘法,但高精度乘法的代码有的精炼但难懂,有的一百多行但容易理解,于是,在本人不懈的努力下,终于找到了一个简洁易懂的高精度乘法的代码,并且大彻大悟(感谢洛谷大佬lei_yu给的思路),接下来的文章中会详细介绍,希望对您有用(制作不易,点个赞吧!!!)(于2025.1.17修改)
2.什么是高精度乘法
乘法,是多个相同加数相加的简便运算,我们在小学时就接触过,乘法口诀表也倒背如流。哪怕是两位数乘两位数,你也许需要花费点时间,不过也能算出来。但如果是一百位数乘上一百位数,一千位数乘上一千位数呢?这就不容易了,因为即使你用草稿纸算半天,你也仍然搞不出来,这就要用到高精度乘法了。与高精度加法和高精度减法一样,也是用数组或容器存储这些数据,模拟两个数相乘的算法。
3.高精度乘法的思路
高精度乘法是模拟了我们小学时的竖式计算,就是让第一个乘数去乘第二个乘数的每一位,例如(图可能画得不好,请见谅):
通过图示,相信大部分人都知道高精度乘法是这么算的了,但当你信心满满的打开c++,发现还有一个问题没解决,就是如何将算出的值相加呢?如果将每个要相加的数都储存在一个列表里,也许会变得简便,但这容易导致数据过大或过多而错误,因为c++的long long储存是有限的,所以此路不通。但如果我们在计算时先不考虑进位,利用循环将每一个所乘的数据都储存在容器或列表里,当下一次相乘时就将以前的数据和它相加,这就能够模拟出错位相加了,先看图示:
循环后,再进行进位处理,依然是需要循环,但多了个判断,老规矩,先看图示:
以上就是错位加法和进位处理的大概过程,在最后去除多余的0,并且反序输出C容器,高精度乘法就完成了
4.真题讲解(洛谷【算法1-1】模拟与高精度 P1303)
题目背景
高精度乘法模板题。
题目描述
给出两个非负整数,求它们的乘积。
输入格式
输入共两行,每行一个非负整数。
输出格式
输出一个非负整数表示乘积。
输入输出样例
输入 #1
1 2
输出 #1
2
说明/提示
每个非负整数不超过 10^2000。
#include<iostream>
#include<vector>
using namespace std; //因为在上文已经详细的讲了,所以这里只强调重点和容易出错的地方
vector<int> CF(vector<int> &A,vector<int> &B){
vector<int> C(8001,0); //括号中的第一个元素是容器的容量,这里选用8001,第二个元素是初始值
for(unsigned int i=0;i<B.size();i++){
for(unsigned int j=0;j<A.size();j++){
C[i+j]+=A[j]*B[i]; //注意这里的i是B容器的下标,j是A容器的下标,不要搞反了
}
}
return C;
}
int main(){
string a,b;
cin>>a>>b;
vector<int> A,B;
for(int i=a.size()-1;i>=0;i--){
A.push_back(a[i]-'0');
}
for(int i=b.size()-1;i>=0;i--){
B.push_back(b[i]-'0');
} //基本的输入,不用说
vector<int> C=CF(A,B);
for(unsigned int i=0;i<A.size()+B.size();i++){ //因为两数相乘所得的积的位数是不可能大于这两数的位数之和的,所以这里是A.size()+B.size()
if(C[i]>=10){
C[i+1]+=C[i]/10;
C[i]=C[i]%10; //进位
}
}
while(C.size()>1 && C.back()==0){ //去除多余的0
C.pop_back(); //C.back()是C容器的末尾,C.pop_back()是删除末尾的元素
}
for(int i=C.size()-1;i>=0;i--){ //反序输出
cout<<C[i];
}
return 0; //收尾
}
5.总结
高精度乘法是在高精度加法和高精度减法基础上的提升,所以相对而言可能比较难懂。本文所讲的高精度乘法的思路就是先将题目化为竖式计算,通过竖式计算得出规律,将规律编写成代码后,再处理进位,接着把多余的0去掉,最后反序输出。总之,本文的高精度乘法想要完全摸清思路和原理,并将这种思维方式运用到实际编程中是很难的(至少对本人而言),毕竟这种解法本人是真想不到。
本文如有错误或者有可以改进的地方,请各位批评指出。另外,本人为初中生,开学后需要准备月考和竞赛,如有消息未能及时回复,也请原谅,谢谢
如有侵权行为,请私信告知,本人会及时将此文章进行处理
感谢观看!!!