一、高精度加法
1.1整体思想:模仿正常的整数计算。整数加法实际上是对应的两个数相加,再加上来自上一次计算的进位。计算后对10取余即为该位运算的结果。此处进位的处理可看代码读懂。注意循环结束后要判断最后相加的两位有没有进位。
1.2.模板代码:
// C = A + B, A >= 0, B >= 0
vector<int> add(vector<int> &A, vector<int> &B)
{
vector<int> C;
int t = 0; //进位
for (int i = 0; i < A.size()||i<B.size(); i ++ ) //整数A和B都加到尽头结束
{
if (i < A.size()) t += A[i]; //A没加完就继续加
if (i < B.size()) t += B[i]; //B没加完继续加
C.push_back(t % 10); //此时t=A+B+进位 对10取余表示该位计算结果
t /= 10; //若有进位则t=1
}
if (t) C.push_back(t); //判断最后一位是否有进位
return C;
}
例题:https://www.acwing.com/problem/content/793/
题解:
#include <bits/stdc++.h>
using namespace std;
vector<int> add(vector<int> &a,vector<int> &b)
{
if (a.size()<b.size()) return add(b,a);
vector<int> c;
int t=0;
for (int i = 0; i < a.size(); i ++ )
{
t+=a[i];
if(i<b.size()) t+=b[i];
c.push_back(t % 10);
t=t/10;
}
if(t) c.push_back(t);
return c;
}
int main()
{
string n,m;
vector<int> a,b;
cin>>n>>m;
for(int i=n.size()-1;i>=0;i--) a.push_back(n[i]-'0');
for(int i=m.size()-1;i>=0;i--) b.push_back(m[i]-'0');
auto c=add(a,b);
for(int i=c.size()-1;i>=0;i--) cout<<c[i];
return 0;
}
二、高精度减法
2.1.注意事项及细节:
1.大整数的存储方式与加法相同。
2. 始终是大的数减去小的数,在进行减法操作前比较大小,换位加-
3.借位问题,(t+10)%10,若t>0,未借位则为本身,若t<0,则说明借位了需加10
4.去除前导0,避免出现最终结果为007这种情况;
2.2模板
// C = A - B, 满足A >= B, A >= 0, B >= 0
vector<int> sub(vector<int> &A, vector<int> &B)
{
vector<int> C;
for (int i = 0, t = 0; i < A.size(); i ++ )
{
t = A[i] - t;
if (i < B.size()) t -= B[i];
C.push_back((t + 10) % 10);
if (t < 0) t = 1;
else t = 0;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
例题:
https://www.acwing.com/problem/content/794/
代码
#include<bits/stdc++.h>
using namespace std;
vector<int> sub(vector<int> &A,vector<int> &B)
{
vector<int> C;
for(int i=0,t=0;i<A.size();i++)
{
t=A[i]-t;
if(i<B.size()) t=t-B[i];
C.push_back((t+10)%10);
if(t>=0) t=0;
else t=1;
}
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
bool cmp(vector<int> &A,vector<int> &B)
{
if(A.size()!=B.size()) return A.size()>B.size();
for(int i=A.size()-1;i>=0;i--)
{
if(A[i]!=B[i])
return A[i]>B[i];
}
return true;
}
int main()
{
string a,b;
vector<int>A,B;
cin>>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;
if(cmp(A,B))
{
C=sub(A,B);
}
else C=sub(B,A),cout<<"-";
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
cout<<endl;
return 0;
}
三、高精度乘法
3.1注意事项及细节
1.将小精度的乘数看成一位数进行操作,进位:t;乘法结果t+=A[i]*b;进位结果:t=t/10;存储当前位计算结果t=t%10
2.去除前导0
3.2模板
// C = A * b, A >= 0, b >= 0
vector<int> mul(vector<int> &A, int b)
{
vector<int> C;
int t = 0;
for (int i = 0; i < A.size() || t; i ++ )
{
if (i < A.size()) t += A[i] * b;
C.push_back(t % 10);
t /= 10;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
例题https://www.acwing.com/problem/content/795/
代码
#include<bits/stdc++.h>
using namespace std;
vector<int> mult(vector<int> &A,int b)
{
vector<int> C;
int t=0;
for(int i=0;i<A.size();i++)
{
t+=A[i]*b;
C.push_back(t%10);
t=t/10;
}
if(t) C.push_back(t);
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
int main()
{
string a;
int b;
cin>>a>>b;
vector<int> A;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
auto C=mult(A,b);
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
}
四、高精度除法
4.1注意事项及细节
1.注意返回余数和商的结果。处理,除数:r=r*10+A[i],被除数:b,商:r/b,余数:r%10;
2.与其它三个不同,在进行运算时,从高位开始计算,for循环的初始位置为A.size()-1。 同时也造成了存储顺序的不同。首位存储的是最高位。
3.得到运算结果后进行数组倒置
4.去除前导0
4.2模板
// A / b = C ... r, A >= 0, b > 0
vector<int> div(vector<int> &A, int b, int &r)
{
vector<int> C;
r = 0;
for (int i = A.size() - 1; i >= 0; i -- )
{
r = r * 10 + A[i];
C.push_back(r / b);
r %= b;
}
reverse(C.begin(), C.end());
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
例题:
https://www.acwing.com/problem/content/description/796/
代码
#include<bits/stdc++.h>
using namespace std;
vector<int>div(vector<int>&A,int b,int &r)
{
vector<int>C;
r=0;
for(int i=A.size()-1;i>=0;i--)
{
r=r*10+A[i];
C.push_back(r/b);
r=r%b;
}
reverse(C.begin(),C.end());
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
int main()
{
string a;
int b,r;
vector<int> A;
cin>>a>>b;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
auto C=div(A,b,r);
for(int i=C.size()-1;i>=0;i--) cout<<C[i];
cout<<endl<<r<<endl;
}
五、小知识
1.大整数在c++中存放在整数数组中,存放顺序为先存个位,再依次存高位(倒序存储)。因为在运算过程中会出现进位的情况,进位为最高位,若最高位存在数组的首位,那进位需要移动大量数据,而最高位存放在数组的末位,则只需要添加即可。省去大量时间。
2.注意输入和输出时都是倒序。
3.用vector建立数组,vector中有size函数,可直接获得数组的长度。
4.存大整数时,先用字符串读入,再通过减‘0’变为整数型存入数组。注意减单引号0
5.reverse(C.begin(),C.end());将数组倒置的函数