大数相加 + 大数相乘

1. 大数相加

题目描述:以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回。
思路:从后往前依次加两个字符串的数字,保留其进位,与下次相加结果再进行相加,直到两个都计算完。最后判断进位是否1(如果有进位的话,一定是1),若有进位,加上去即可。

string solve(string s, string t) {
        // write code here
        int carry = 0, tmp1 = 0, tmp2 = 0;
        int n1 = s.size() - 1, n2 = t.size() - 1;
        string res;
        while(n1 >= 0 || n2 >= 0){
            if(n1 >= 0)
                tmp1 = s[n1] - '0';        // 保留第一个字符串的第一个数字
            else
                tmp1 = 0;
            if(n2 >= 0)
                tmp2 = t[n2] - '0';        // 保留第二个字符串的第一个数字
            else
                tmp2 = 0;
            int sum = tmp1 + tmp2 + carry;     // 将其相加
            carry = sum / 10;                  // 保留进位
            res = to_string(sum % 10) + res;   // 保留相加后的低位数字
            n1--; n2--;
        }
        if(carry)                              // 判断是否有进位,若有进位,直接加上即可。    
            res = '1' + res;
        return res;
    }

2. 大数相乘

题目描述:给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
思路:

  1. 两个数字相乘之后的长度最多是两个数字长度之和,即 len(res) <= len(num1) + len(num2);
  2. 模拟竖式乘法即可,将num1的第i位(高位从0开始)和num2的第j位相乘的结果在乘积中的位置是[i+j, i+j+1],并在每次计算时都要加上上次计算后的 进位,具体看代码与示例。
  3. 注意去掉前导0,因为申请字符串长度时候是len(num1) + len(num2),但结果长度可能大于这个数,所以会导致前面有若干个0,我们需要将其去掉。

示例:53 * 54

  1. 申请一个大小为4的字符串s
  2. 计算3 * 4 = 12,将2保存到 s最后一位,并将进位 1 保存到前一位;
  3. 计算3 * 5 = 15,将此结果加上上一步的进位1,得16,将6保存到上一位的进位处,并将此步骤的进位1放在6的前一位;
  4. 计算 5 * 4 = 20, 加上上一步的进位,低位与进位与上一步位置一样
  5. 计算 5 * 5 = 25 ,加上上一步进位,低位是上一步的进位位置,进位是上一步进位的前一个位置。
  6. 最后去掉前导0
string multiply(string num1, string num2) {
        // 两数相乘的最大位数 就是 sizeof(num1) + sizeof(num2);
        // num1的第i位(高位从0开始)和num2的第j位相乘的结果在乘积中的位置是[i+j, i+j+1]
        int l1 = num1.size() - 1, l2 = num2.size() - 1;
        string res(l1 + l2 + 2, '0');
        for(int i = l1; i >= 0; --i){
            for(int j = l2; j >= 0; --j){
                int tmp = res[i + j + 1] - '0' + (num1[i] - '0') * (num2[j] - '0');
                res[i + j + 1] = tmp % 10 + '0';           // 保存低位
                res[i + j] += tmp / 10;					   // 保存进位
            }
        }

        // 删除前导 0
        for(int i = 0; i < l1 + l2 + 2; ++i){
            if(res[i] != '0')
                return res.substr(i);
        }
        return "0";
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值