大写字母表示大整数,小写字母表示小整数。len(A)表示位数。
大整数一般存到数组中,从后往前依次存入数组。例如:
原因是当我们需要进位时比较方便,只需要在数组最后添加一个数即可。
例一:高精度加法
算法思路:
每一次都是:A+B+进位(0或1),若A或B不存在则为0。
代码如下:
#include<iostream>
#include<vector>
using namespace std;
const int N = 1000010;
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 的第 i 位上的数字(如果有的话)
if(i < A.size()) t += A[i];
//加上B的第i位上的数字(如果有的话)
if(i < B.size()) t += B[i];
//将每次的相加结果加入到C中
C.push_back(t%10);
t = t/10;
}
//若最后一次的进位位1,则加入到C中
if(t) C.push_back(1);
return C;
}
int main()
{
string a,b;
vector<int> A,B;
cin >> a >> b;
//将a倒序加入到A中
for(int i = a.size() - 1;i >= 0;i--) A.push_back(a[i] - '0');
//将b 倒序加入到B中
for(int i = b.size() - 1;i >= 0;i--) B.push_back(b[i] - '0');
auto C = add(A,B);//auto可以自动判断数据类型
for(int i = C.size() - 1;i >= 0;i--) printf("%d",C[i]);
return 0;
}
例二:高精度减法
算法思路:
首先,判断A和B谁大,若A大则计算A-B,若B大,则计算-(B-A)。然后,判断Ai-Bi-t是否大于0,若大于等于0说明没有借位,直接将Ai-Bi-t加入到容器,若小于0,则说明有借位,这时将Ai-Bi+10-t加入到容器中。最后别忘了去掉前导0,比如:结果为003,则需去掉前面的两个0。
代码如下:
#include<iostream>
#include<vector>
using namespace std;
//判断A是否>=B
bool cmpare(vector<int> &A,vector<int> &B)
{
if(A.size()!=B.size()) return A.size() > B.size();
else{
for(int i = A.size() - 1;i >= 0;i--)
{
if(A[i]!=B[i]) return A[i] > B[i];
}
}
//A=B
return true;
}
vector<int> sub(vector<int> &A,vector<int> &B)
{
vector<int> C;
int t = 0;
for(int i = 0;i <= A.size();i++)
{
t = A[i] -t;
//若B的第i个位置存在
if(i < B.size()) t -= B[i];
//若t>=0,则结果为t本身,若t<0,则结果为向高位借一位之后的数
C.push_back((t+10)%10);
if(t>=0){
//若t>=0说明没有借位
t = 0;
}else{
//若t<0说明借位了
t = 1;
}
}
//去掉前导0(比如:132-121=011)
while(C.size() > 1&&C.back()==0)
{
C.pop_back();
}
return C;
}
int main()
{
vector<int> A,B;
string 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');
if(cmpare(A,B))
{
auto C = sub(A,B);
for(int i = C.size() - 1;i >= 0;i--) printf("%d",C[i]);
}else{
auto C = sub(B,A);
printf("-");
for(int i = C.size() - 1;i >= 0;i--) printf("%d",C[i]);
}
return 0;
}
例三:高精度乘法
算法思路:大整数A和小整数b相乘,将b看成一个整体与A的每一位相乘。每次的结果为:(A0b+t0)%10,其中t0为上一步的进位,t1 = (A0b+t0)/10。注意:①要保证最后一步的进位加入到结果C中,需要在for循环中加一个条件,即t!=0时也要循环。②若结果全为0,需要去掉多余的前导0;
代码实现:
#include<iostream>
#include<vector>
using namespace std;
vector<int> mul(vector<int> &A,int b)
{
vector<int> C;
int t = 0;
//i < A.size()||t的作用是乘到最后一位时若有进位时,即t!=0,将进位加入到C中。
for(int i = 0;i < A.size()||t;i++)
{
if(i < A.size()) t += A[i]*b;
C.push_back(t%10);
t = t/10;
}
//去掉前导0
while(C.size() > 1&&C.back()==0)
{
C.pop_back();
}
return C;
}
int main()
{
string a;
int b;
vector<int> A;
cin >> a >> b;
for(int i = a.size() - 1;i >= 0;i--) A.push_back(a[i] - '0');
auto C = mul(A,b);
for(int i = C.size() - 1;i >= 0;i--) printf("%d",C[i]);
return 0;
}
例四:高精度除法
算法思路:
大整数A和小整数b相除,r为每一步的余数,C为每一步的结果。
代码如下:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//注意r是引用,可以返回r在函数中的值
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];
//注意不要写成r / 10
C.push_back(r/b);
r = r%b;
}
//C要翻转一下,使用还函数必须加#include<algorithm>
reverse(C.begin(),C.end());
//去掉前导0
while(C.size() > 1&&C.back() == 0)
{
C.pop_back();
}
return C;
}
int main()
{
vector<int> A;
int b;
string a;
cin >> a >>b;
for(int i = a.size() - 1;i >= 0;i--) A.push_back(a[i] - '0');
int r;
auto C = div(A,b,r);
for(int i = C.size() - 1;i >= 0;i--) printf("%d",C[i]);
cout << endl << r << endl;
return 0;
}