注:
1.截图与代码来自acwing
2.仅作为本人的学习笔记使用
3.有理解不对的地方欢迎大佬指出orz
1.用途:
让10的100次方等大数参与程序运行(long long表示的范围只有10的18次方数量级)
2.存大数怎么实现?
用数组存,把每位拆开放数组里,第0位存个位,倒着存
一、加法
1.运算:模拟人工加法(竖式)
每次运算是相当于三个数相加:A,B,t(进位数)
2.过程
①存储
②运算
ps:
#include<vector>;
a.push_back(5); //在a的最后一个向量后插入一个元素,其值为5
a.size(); //返回a中元素的个数;
3.代码
#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);//如果b长的话,把这两个数反过来,重新调用这个函数
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 a, b;
vector<int> A, B;
cin >> a >> b;//a"1,2,3,4,5,6"
for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');//A[6,5,4,3,2,1]
for (int i = b.size() - 1; i >= 0; i -- ) B.push_back(b[i] - '0');
auto C = add(A, B);
for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
cout << endl;
return 0;
}
二、减法
1.每个C都是A-B-t(t是看看上一次运算有没有借位)
2.如果A>=B的话,那就正常,如果A<B的话,算B-A然后加个负号
3.代码
#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 -- )//如果这两个位数相等的话,从A的最后一位开始比,也就是从最高位开始比
if (A[i] != B[i])
return A[i] > B[i];//在第i位:A大return1,B大return0
return true;//如果二者相等则会走到这一步,return 1
}
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;//如果上次计算有借位,则t是1
if (i < B.size()) t -= B[i];//如果B还有的话,减去B(达成A-B)
C.push_back((t + 10) % 10);//现在的t是A-进位-B,比如4-1-2模出来是(1+10)%10=1,如果是4-1-5是(-2+10)%10=8(就是不管是否进位,先把这个10默认加上,对本来不需要进位的情况不会产生什么影响)
if (t < 0) t = 1;//在这里判断是不是触发借位条件了(A-进位-B是负数)
else t = 0;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();//除掉前导0,只要不是只有一位,并且C数组最后是0,那就删掉最后的数组元素
return C;
}
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');
//两个for循环,不是一个
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;
}
三、乘法
#include <iostream>
#include <vector>
using namespace std;
vector<int> mul(vector<int> &A, int b)
{
vector<int> C;
int t = 0;
for (int i = 0; i < A.size() || t; i ++ )//A还有或者t还有都会让循环进行
{
if (i < A.size()) t += A[i] * b;//A还有就加
C.push_back(t % 10);//把t的最后一位存C里
t /= 10;//剩给下一个数的时候少一位
}
while (C.size() > 1 && C.back() == 0) C.pop_back(); //个位乘出来是3,但后面t落到C里是0,那就C倒置输出就会出现03,为了避免,返回C前先去掉前导0(我左思右想没想到这样的例子,然后看帖子有人说是避免b=0的)
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 = mul(A, b);
for (int i = C.size() - 1; i >= 0; i -- ) printf("%d", C[i]);
return 0;
}
双精版
#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/=10;
}
if(t)C.push_back(t);
return C;
}
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;
}
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;
C.push_back(0);
for(int i=A.size()-1;i>=0;i--){//从A数组或B数组的高位开始单精乘
C=add(C,mul(B,A[i]));
C.insert(C.begin(),0);
C[0]=0;
for(int i=C.size()-1;i>=1;i--){
cout<<C[i];
}
return 0;
}
四、除法
和之前的不同,这个得从高位开始处理,所以函数里的for循环从A.size()-1往0执行
r是余数,r每次留下来都*10再加上下一个掉下来的A,有点像倒置
代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> div(vector<int> &A, int b, int &r)//这个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();//去前导0
return C;
}
int main()
{
string a;
vector<int> A;
int B;
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 -- ) cout << C[i];
cout << endl << r << endl;
return 0;
}