一、大数加法
1.1 实现思路:
步骤:
- 数字利用字符串读入
- 把字符串翻转存入两个整型数组A,B(相当于每个数字的第一个元素的位置是这个大数的最后一位,这样是为了计算简单)
- 把低位到高位,累加,进位,村余
- 把数组C从高位到低位依次输出
样例:
1.2 代码:
#include<iostream>
#include<vector>
using namespace std;
vector<int> add(vector<int>& A, vector<int>& B) {//传入地址而不是向量,不必拷贝整个向量,增加速度
if (A.size() < B.size()) return add(B, A);//为了避免情况讨论,这里默认A位数比B多,否则翻转B,A以满足这一条件
vector<int> C;
int t = 0;//t用来标记进位
for (int i = 0; i < A.size(); i++) {//A位数比B多,A的位数做循环次数,保证所有位循环完
t += A[i];//A[i]必然存在
if (i < B.size()) t += B[i];
C.push_back(t % 10);
t /= 10;
}
//仍然可能存在一个进位没有输出到C中,因为此时的C和A位数相同,可能C的位数大于A的,如50+50,此时C为100,
if (t) C.push_back(t);
return C;
}
int main() {
string a, b;
vector<int> A, B;
cin >> a >> b;//由于输入数据较大,首先将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');//在模拟手算加法时候,要从个位开始处理,不断扩展到最高位,为了方便处理,将字符串逆置传入数组当中,这样可以从a[0]到a[n]开始由低至高处理
auto c = add(A, B);//通过高精度加法操作得到A+B将其传入数组C
for (int i = c.size() - 1; i >= 0; i--) cout << c[i];
cout << endl;
return 0;
}
二、大数减法
2.1 思路:
步骤:
- 大数利用字符串读入
- 把字符串翻转存入两个整型数组A,B
- 若A<B,则交换A,B输出负号(这样可以保证被减数的位数比减数多)
- 把低位到高位,逐位求差,借位,存差
- 把数组C从高位到低位依次输出
样例:
2.2 代码:
#include<iostream>
#include<vector>
using namespace std;
//判断二者数字的大小
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;
}
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;
if(i<B.size()) {
t-=B[i];//相同位数相减
}
C.push_back((t+10)%10);//这一步包括t>=0和t<0两种情况
if(t<0) t=1;//小于0,说明借位了
else t=0;
}
//目前二者相减C的位数和A相同,存在C实际位数更小的情况,因此要去掉前导零
while(C.size()>1&&C.back()==0) C.pop_back();
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;
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.2 思路:
步骤:
1.大数利用字符串读入
2. 把字符串翻转存入两个整型数组A,B
3. 从低位到高位,累加乘积,进位,存余
4. 把数组C从高位到低位依次输出
样例:
这是我们常规计算乘法的方法:每一位相乘,进位然后存余
我们一般做大数乘法的方法:每一位相乘之后先累加,再进位存余
进而抽象之后的算法实现:
3.2 代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int A[N],B[N],C[N];
int la,lb,lc;
void mul(int A[],int B[],int C[]){
for(int i=0;i<la;i++)
for(int j=0;j<lb;j++){
C[i+j]+=A[i]*B[i];//累加乘积
C[i+j+1]+=C[i+j]/10;//进位
C[i+j]%=10;//存余
}
while(lc && C[lc]==0) lc--;//处理前导0
}
int main ()
{
string a,b;
cin>>a>>b;
la=a.size(),lb=b.size();
lc=la+lb;
for(int i=la-1;i>=0;i--) A[la-1-i]=a[i]-'0';
for(int i=lb-1;i>=0;i--) B[lb-1-i]=b[i]-'0';
mul(A,B,C);
for(int i=lc;i>=0;i--) cout<<C[i];
return 0;
}
四、大数除法
4.1 思路:
步骤:
- 大数利用字符串读入
- 把字符串翻转存入整型数组A
- 从高位到低位,当前被除数,存商,存余数
- 把数组C从高位到低位依次输出
样例:
4.2 代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//A/b,商是C,余数是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];//先算出此时的被除数
C.push_back(r/b);//存商
r%=b;//此时剩下的余数
}
reverse(C.begin(),C.end());//存完之后最高位在C[0],所以需要逆置一下
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');
int r;
vector<int>C=div(A,b,r);
for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]);
cout<<endl<<r<<endl;
return 0;
}