大数运算(加减乘除)

一、大数加法

1.1 实现思路:

步骤:

  1. 数字利用字符串读入
  2. 把字符串翻转存入两个整型数组A,B(相当于每个数字的第一个元素的位置是这个大数的最后一位,这样是为了计算简单)
  3. 把低位到高位,累加,进位,村余
  4. 把数组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 思路:

步骤:

  1. 大数利用字符串读入
  2. 把字符串翻转存入两个整型数组A,B
  3. 若A<B,则交换A,B输出负号(这样可以保证被减数的位数比减数多)
  4. 把低位到高位,逐位求差,借位,存差
  5. 把数组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 思路:

步骤:

  1. 大数利用字符串读入
  2. 把字符串翻转存入整型数组A
  3. 从高位到低位,当前被除数,存商,存余数
  4. 把数组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;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值