8.AcWing792.高精度减法(AcWing算法基础课二刷)

关键词:高精度减法、vector(容器)

地位:算法竞赛普遍涉及,在笔试、面试是一个比较重要的考点。

高精度的很多知识点在高精度加法已经介绍过了,高精度的加减乘除有很多相同之处。即便如此,文中依然保留两种代码:用vector实现的高精度、数组实现的高精度。

(高精度减法压位用的太少了)

高精度加法的链接就在下方,还没了解高精度的读者可以先了解这篇文章:

7.AcWing791.高精度加法(AcWing算法基础课二刷)_浩子诚的博客-CSDN博客

高精度减法依然可以采用竖式计算的方法解决。此时保证函数中的A一定大于等于B(之后会解释原因),从个位开始相减。如下图所示:在第i位中,A-B的结果是A_{i}-B_{i}-t。如果这个式子为负数,那么要想前一位借1,即加上10;t表示后一位是否借1,所以t只有1和0两种情况。实现方法和高精度加法基本一致,也是使用vector<int>来模拟高精度。

那么如何判断A-B的关系?此时我们可以先比较A和B字符串的“大小”(不可以直接用字典序),然后再判断A和B的关系。我们是这样判断的:如果A和B位数相等,则判断A和B的字典序;如果不相等,那当然是位数大的数字较大。如果A小于B,则先输出负号,再转化为B-A。这就是上述操作中A一定大于B的原因。

大家可以结合下图(y总算法基础课的高精度减法)来理解上述的两段话。

下面是基于vector容器实现的高精度减法模板:

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
bool cmp(string a,string b)//判断a是否大于等于b
{
    if(a.size()!=b.size()) //先判断a和b的位数关系
    return a.size()>b.size();
    else//位数相同根据字典序判断
    {
        if(a>=b) return true;
        else return false;
    }
}
//两个高精度整数的减法
vector<int> sub(vector<int> &a,vector<int> &b)
{
    int t=0;//t表示是否借1
    vector<int> ans;//ans逆序(个位下标是0)存储高精度整数
    for(int i=0;i<a.size();i++)//从个位加到最高位
    {
        //让这一次的t成为ai-bi-t(上一次的t)
        //ai-bi-t可以先让ai-t,在判断bi是否有数
        t=a[i]-t;
        if(i<b.size()) t-=b[i];//b的第i位存在数字
        ans.push_back((t+10)%10);//t可能为负数,加上10
        //向前一位借1,之后模10作为个位数存储
        if(t<0) t=1;//如果t<0说明向前借了1,下一次的t是1
        else t=0;//否则没有借0,下一次不需要减1
    }
    //去除前导零操作,如果最高位(容器末尾)是0,则需要删除
    //直到数组长度剩下1(即结果是0)或者没有前导零了为止
    while(ans.size()!=1&&ans.back()==0) ans.pop_back();
    return ans;//记得要返回vector容器
}
int main()
{
    string A,B;
    cin>>A>>B;
    vector<int> a,b,c;
    //字符串转vector存储
    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(cmp(A,B))//判断A是否比B大(或相等)
    {
        //如果是,计算a-b
        c=sub(a,b);
    }
    else//如果不是
    {
        //输出负号、之后计算b-a
        printf("-");
        c=sub(b,a);
    }
    //逆序输出高精度
    for(int i=c.size()-1;i>=0;i--)
    printf("%d",c[i]);
    return 0;
}

接下来展示手写数组模拟高精度减法(可以通过792题):

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;//题目的位数最多是100000位
char A[N],B[N];
int a[N],b[N],c[N];
bool cmp(char a[],char b[])
{
    if(strlen(a)==strlen(b))//位数相同
    return strcmp(a,b)>=0;//strcmp比较两个数组的字典序
    //大于0,A字典序大;等于0,字符串相等;小于0,B字典序大
    else return strlen(a)>strlen(b);//否则比较位数
}
int main()
{
    scanf("%s%s",A,B);
    if(!cmp(A,B))
    {
    
        swap(A,B);//swap也可以交换数组
        printf("-");
    }
    int alen=strlen(A),blen=strlen(B);
    //字符转整数数组存储
    for(int i=0,j=alen-1;i<alen;i++,j--)
    a[i]=A[j]-'0';
    for(int i=0,j=blen-1;i<blen;i++,j--)
    b[i]=B[j]-'0';
    //思想和用vector容器一样,就不赘述了
    int clen=max(alen,blen);
    int t=0;
    for(int i=0;i<clen;i++)
    {
        t=a[i]-t;
        if(i<blen) t-=b[i];
        c[i]=((t+10)%10);
        if(t<0) t=1;
        else t=0;
    }
    //删除前导0操作
    while(c[clen-1]==0&&clen!=1) clen--;
    for(int i=clen-1;i>=0;i--) printf("%d",c[i]);
    return 0;
}

用数组模拟稍微比vector要快一点。

参考链接/文献:

Ⅰ.AcWing——算法基础课,2019,闫学灿 活动 - AcWing

Ⅱ.AcWing792.高精度减法 活动 - AcWing

感谢您的支持

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值