一、你需要知道
1、高精度数无法被int或者long long类型直接保存,需要用字符数组或者string类来保存。
2、字符串保存的高精度数,下标【0】存放着高精度数的最高位,下标【字符串长度-1】存放着高精度数的个位。
3、为了方便计算,符合人类正常的计算思维,需要将高精度数进行倒置,倒置后用int数组保存高进度数,此时下标【0】存放个位,下标【长度-1】存放最高位。
4、为了本套模版的通用性,将模拟加、减、乘、除的过程单独分离出来处理,模拟完成后再去进行进位或者借位操作(对比代码理解)。
5、计算完成后必须删除前导零,例如000180,应该输出180。
二、高精度算法
高精度加法步骤:
1. 从个位数开始,逐位相加,保留进位;
2. 如果有进位,继续向高位相加,直到所有位数相加完毕。
#include<bits/stdc++.h>
using namespace std;
const int N=205;
string s1,s2;
int a[N],b[N],c[N];
int main()
{
cin>>s1>>s2;
//倒置
int l1=s1.size(),l2=s2.size(),l3=max(l1,l2)+1;
for(int i=0;i<l1;i++) a[l1-1-i]=s1[i]-'0';
for(int i=0;i<l2;i++) b[l2-1-i]=s2[i]-'0';
//模拟加法
for(int i=0;i<l3;i++)
c[i]=a[i]+b[i];
//处理进位、留个位
for(int i=0;i<l3;i++)
{
c[i+1]+=c[i]/10;
c[i]%=10;
}
//删去前导零
while(c[l3-1]==0 && l3>1) l3--;
for(int i=l3-1;i>=0;i--) cout<<c[i];
return 0;
}
高精度减法步骤:
1. 从个位数开始,逐位相减,借位不够时向更高位借位;
2. 如果需要借位,继续向更高位相减,直到所有位数相减完毕。
#include<bits/stdc++.h>
using namespace std;
string s1,s2;
const int N=205;
int a[N],b[N],c[N];
int main()
{
cin>>s1>>s2;
int l1=s1.size(),l2=s2.size(),l3=max(l1,l2);
//倒置
for(int i=0;i<l1;i++) a[l1-1-i]=s1[i]-'0';
for(int i=0;i<l2;i++) b[l2-1-i]=s2[i]-'0';
//模拟减法
for(int i=0;i<l3;i++)
c[i]=a[i]-b[i];
//处理借位
for(int i=0;i<l3;i++)
{
if(c[i]<0){
c[i+1]--;
c[i]+=10;
}
}
//删除前导零
while(c[l3-1]==0&&l3>1) l3--;
for(int i=l3-1;i>=0;i--) cout<<c[i];
return 0;
}
高精度乘法步骤:
1. 逐位相乘,保留进位;
2. 将每一位的乘积相加,得到最终结果。
#include<bits/stdc++.h>
using namespace std;
string s1,s2;
int a[105],b[105],c[205]={0};
int main()
{
cin>>s1>>s2;
//提前倒置两个大数
int l1=s1.size(),l2=s2.size(),l3=l1+l2;
//i是字符串原本的下标、j是字符串倒置后的下标
for(int i=0,j=l1-1;i<l1;i++,j--) a[j]=s1[i]-'0';
//公式实现: 将下标i--->下标 l2-i-1
for(int i=0;i<l2;i++) b[l2-i-1]=s2[i]-'0';
//开始模拟乘法
//乘法公式 c[i+j]+=a[i]*b[j]
for(int i=0;i<l1;i++)
for(int j=0;j<l2;j++)
c[i+j]+=a[i]*b[j];
//进位、留个位
for(int i=0;i<l3;i++)
{
c[i+1]+=c[i]/10;//第i位进位到i+1位
c[i]%=10; //个位的留到第i位
}
//删去前导0
while(c[l3-1]==0 && l3>1) l3--;
//输出
for(int i=l3-1;i>=0;i--) cout<<c[i];
return 0;
}
高精度除以低精度步骤:
1. 从被除数的最高位开始,逐位与除数相除,得到商和余数;
2. 将余数乘以10,再与下一位进行除法运算,直到所有位数都计算完毕。
#include<bits/stdc++.h>
using namespace std;
string s1;
int a[110],c[110],b;
int main()
{
//低精度除数为13
b=13;
cin>>s1;
int l1=s1.size();
//倒置
for(int i=0;i<l1;i++) a[l1-1-i]=s1[i]-'0';
// 模拟除法竖式
int l3=l1-1;//商的长度,可以优化成l1-l2+1
int r=0;//余数初始化为0
for(int i=l1-1;i>=0;i--){
c[i]=(r*10+a[i])/b;
r=(r*10+a[i])%b;
}
//删除前导零
while(c[l3-1]==0&&l3>1) l3--;
//逆序输出
for(int i=l3-1;i>=0;i--)
cout<<c[i];
cout<<endl<<r;
return 0;
}
高精度除以高精度步骤:
1. 将被除数和除数都倒置,从被除数的最高位开始逐步进行除法运算。
2. 比较被除数(一部分)和除数的大小,如果被除数比较大,则减去一次除数,商对应位+1
3. 如果被除数小,再与被除数的下一位结合后,重复第2步,直至所有位数都计算完毕。
#include<bits/stdc++.h>
using namespace std;
string s1,s2;
const int N=305;
int a[N],b[N],c[N],l1,l2,l3;
bool cmp(int i)被除数a从最高位到第i位,是否大于等于除数b(从最高位到第0位)
{
//比b最高位还要高位的位置上有数字
if(a[i+l2]>0) return true;
for(int j=l2-1;j>=0;j--)//从高位到低位比较
{
if(a[i+j]>b[j]) return true;
else if(a[i+j]<b[j]) return false;
}
//相等
return true;
}
int main()
{
cin>>s1>>s2;
//倒置
l1=s1.size(),l2=s2.size(),l3=l1-l2+1;
for(int i=0;i<l1;i++) a[l1-1-i]=s1[i]-'0';
for(int i=0;i<l2;i++) b[l2-1-i]=s2[i]-'0';
//模拟除法
for(int i=l3-1;i>=0;i--){//从高位开始
while(cmp(i)){//够减 ,做一次减法
c[i]++;//对应位的商加一
//模拟减法
for(int j=0;j<l2;j++){//从低位开始
if(a[i+j]>=b[j]) a[i+j]-=b[j];//减得下
else{//减不下
a[i+j]=a[i+j]+10-b[j];
a[i+j+1]--;//向高位借位
}
}
}
}
//商、余数前导零
while(c[l3-1]==0&&l3>1) l3--;
while(a[l2-1]==0&&l2>1) l2--;
for(int i=l3-1;i>=0;i--) cout<<c[i];
cout<<endl;
for(int i=l2-1;i>=0;i--) cout<<a[i];
return 0;
}