上海交通大学考研机试题——大数运算

题目描述

给定两个整数 a a a b b b,请你依次计算并输出 a + b a+b a+b a − b a−b ab a × b a×b a×b 的结果。

注意: a , b a,b a,b 不含前导零。

输入格式

第一行包含整数 a a a

第二行包含整数 b b b

输出格式

第一行输出 a + b a+b a+b 的结果。

第二行输出 a − b a−b ab 的结果。

第三行输出 a × b a×b a×b 的结果。

数据范围
∣ a ∣ |a| a, ∣ b ∣ |b| b < 1 0 400 10^{400} 10400

输入样例:

20000000000000000
4000000000000000

输出样例:

24000000000000000
16000000000000000
80000000000000000000000000000000


从题目的数据范围可以看出我们需要使用高精度算法,分别是:高精度加法,高精度减法,高精度*高精度
读者若对以上算法不熟悉可以将对应代码模拟一遍,背过即可
此题的考察的算法不难。不过需要考察正负号的问题
我们可以使用substr函数将读入的字符串从1到末尾截取下来
用na,nb保存我们的数字的正负号,可以将情况分为两大类
1、符号相同
2、符号相反
具体情况看代码注释

代码如下
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;

int cmp(vector<int> A,vector<int> B)//比较函数
{
    if(A.size()<B.size()) return -1;
    if(A.size()>B.size()) return 1;

    for(int i=A.size()-1;i>=0;i--)
        if(A[i]<B[i]) return -1;
        else if(A[i]>B[i]) return 1;
    return 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()||t;i++)
    {
        if(i<A.size()) t+=A[i];
        if(i<B.size()) t+=B[i];
        C.push_back(t%10);
        t/=10;
    }
    return C;
}

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);
        if(t<0) t=1;
        else t=0;
    }
    while(C.size()>1&&C.back()==0) C.pop_back();
    return C;
}

vector<int> mul(vector<int> A,vector<int> B)//乘法模板
{
    int t=0;
    vector<int> C(A.size()+B.size(),0);
    for(int i=0;i<A.size();i++)
        for(int j=0;j<B.size();j++)
            C[i+j]+=A[i]*B[j];

    for(int i=0;i<C.size();i++)
    {
        t+=C[i];
        C[i]=t%10;
        t/=10;
    }
    while(C.size()>1&&C.back()==0) C.pop_back();
    return C;
}

void print(vector<int> A)//输出
{
    for(int i=A.size()-1;i>=0;i--) cout<<A[i];
    cout<<endl;
}

int main()
{
    string a,b;
    cin>>a>>b;
    int na=1,nb=1;
    if(a[0]=='-') na=-1,a=a.substr(1);//用substr扣掉符号
    if(b[0]=='-') nb=-1,b=b.substr(1);

    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');

    if(na*nb>0)//如果两个符号相同
    {
        if(na<0) cout<<"-";//na<0 nb也<0 相加为"-"
        print(add(A,B));
        bool has_swap=false;//记录是否交换
        if(cmp(A,B)<0)//B较大
        {
            has_swap=true;//交换
            swap(A,B);
            swap(na,nb);
        }
        auto C=sub(A,B);//做减法
        if(na>0&&has_swap||na<0&&!has_swap)
        //第一种情况:两数都大于0 且交换则B较大 A-B<0
        //第二种情况:两数都小于0 且不交换说明去掉符号的A更大则A-B<0
        {
            if(C.size()>1||C[0]>0)//不为0
                cout<<"-";
        }
        print(C);
        print(mul(A,B));
    }
    else   //符号相反
    {
        bool has_swap=false;//记录是否交换
        if(cmp(A,B)<0)//B去掉符号更大交换
        {
            has_swap=true;
            swap(A,B);
            swap(na,nb);
        }
        auto C=sub(A,B);//A+B AB符号为异号 加法变为减法
        if(na<0&&(C.size()>1||C[0]>0)) cout<<"-";//na<0 nb>0且C不为0
        //第一种情况A>0 B<0 且B的绝对值这时交换位置 |B|-A为正数实际A+B为负数
        //第二种情况A<0 B>0 且B的绝对值更小不交唤|A|-B为正数实际A+B为负数
        print(sub(A,B));
        if(na>0&&has_swap||na<0&&!has_swap) cout<<"-";
        //na>0 nb<0 且发生交换原来是na<0,nb>0的减法且|B|较大差为负数。现在为绝对值较大的正数B+|A|
        //na<0 nb>0 且不发生交换原来是na<0,nb>0的减法且|A|较大差为负数,现在为|A|+B
        print(add(A,B));//符号相反的减法可变为加法
        if(a!="0"&&b!="0") cout<<"-";//a,b都不为0
        print(mul(A,B));
    }
    return 0;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值