AcWing 792. 高精度减法(数组模拟,C++)

题意

给定两个正整数,计算它们的差,计算结果可能为负数。
正整数长度的范围是1到100000。

分析

1.先把两个数分别倒序存储在数组中,即最低位在最左边,最高位在最右边。

2.判断A和B哪个数更大,如果A大于B,则计算结果是正数;如果A等于B,则
计算结果是0,;如果A小于B,则计算结果是负数。

3.在进行减法运算时,是从最低位开始相减的;如果A在某个数位上的数比B小,
则A向前一个高位借一个1(即相当于当前数位的10);最后再去掉A的前导零。

4.最后倒序输出。

代码

#include <iostream>

using namespace std;

const int N = 1e5 + 10;

//a[N]为输入的第一个数,b[N]为输入的第二个数,c[N]为a[N]减去b[N]的结果
int a[N], b[N], c[N];
//cnt1是a[N]的长度,cnt2是b[N]的长度,cnt3是c[N]的长度
int cnt1, cnt2, cnt3;

//将大的数减去小的数会更容易计算,因此这里需要比较下输入的两个数的大小
//判断是否有A >= B
bool cmp(int a[], int b[]) {
    //如果两个数位数不相同,则比较位数
    if (cnt1 != cnt2) return cnt1 > cnt2;
    
    //从最高位开始比较两个数的大小
    for (int i = cnt1; i >= 1; i--)
        if (a[i] != b[i])
            return a[i] > b[i];
    
    //比较完所有位置上的数,发现都相同,返回true        
    return true;
}

//len1为较大的那个数的位数,len2为较小的那个数的位数
int sub(int a[], int b[], int len1, int len2) {
    int t = 0;//t为借位的数
    
    //从低位开始相减,当前位置的数不够大,则向更高的那个位置借位
    for (int i = 1; i <= len1; i++) {
        t = a[i] - t;
        if (i <= len2) t -= b[i];//判断b[]是否还有位数可以减
        
        /*下面这行需要注意一下,如果t >= 0,那么(t + 10) % 10还是等于原来的t;
          如果t < 0, 那么(t + 10) % 10就等于原来的t加上10*/
        c[i] = ((t + 10) % 10);
        
        /*然后更新t,如果t < 0,则说明a[]当前位的数是小于b[]当前位的数,
          因此需要向前一位借一个1,相当于给a[]当前位增加了10;
          如果t >= 0,则说明a[]当前位的数是大于等于b[]当前位的数,
          不需要向前一位借一个1*/
        if (t < 0) t = 1;
        else t = 0;
    }
    
    /*减法运算有可能会产生前导0,因此这里需要去掉前导0;
      只要c数组的长度大于1且从最高位开始有连续的0,就去掉这些0*/
    while (len1 > 1 && c[len1] == 0) len1--;
    
    //返回相减运算结果的长度
    return len1;
}

int main() {
    string x, y;
    cin >> x >> y;
    
    //将x倒序存储到a[]中
    for (int i = x.size() - 1; i >= 0; i--)
        a[++cnt1] = x[i] - '0';
     
    //将y倒序存储到b[]中  
    for (int i = y.size() - 1; i >= 0; i--) 
        b[++cnt2] = y[i] - '0';
    
    //判断A和B之间的关系
    if (cmp(a, b)) {
        cnt3 = sub(a, b, cnt1, cnt2);
    } else {
        cnt3 = sub(b, a, cnt2, cnt1);
        cout << '-';
    }
    
    for (int i = cnt3; i >= 1; i--)
        printf("%d", c[i]);
        
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值