大数加法和大数乘法

面试或者笔试的时候经常会遇到这样的题目,比如写一个计算两数之和的程序。如果对于加数与和有限制,比如说,保证不会溢出,那么还好,如果没有限制,很可能就会调入陷阱,因此靠考虑溢出的情况,这个时候就需要考虑用字符串模拟加法运算了,乘法也是一样。

用字符串模拟加法运算其实很简单,两个数相加,和的长度最长为较长字符串+1,然后对应位分别相加,注意加上进位,后期可以补上代码。这里主要说下大数乘法。

大数乘法需要模拟乘法的运算,其实写一个竖式计算就可以看出来了,比如56*23,这里就不写竖式了,直接写结果吧,我们注意到

3*6 = 8(进位1)

3*5 + 2*6 + 1 = 8(进位2)

2*5 + 2 = 2(进位1)

于是结果为1288,上面的计算过程,可以看作是将23倒过来,变为32,然后呢,3和6对齐,相乘;然后移位,56与32对齐,对应位相乘,和相加,再加上进位;然后再移位,2和5对齐,相乘,加上进位,得到最终结果。这个过程类似什么?对了,类似卷积,是的,信号处理里面的卷积计算,倒序,相乘相加,明白了这点,就不难写出代码了,其实就是普通卷积的代码:

char *EX_BigMultiply(char *a, char *b)
{
    if (CheckInput(a, b)) {  检查a、b的状态,并做相关处理,比如是否是数字串,正负等等,实际情况是博主也没实现这个函数- -
        return NULL;
    }

    int len_a = strlen(a);
    int len_b = strlen(b);

    int cnt = len_a + len_b - 1; //记录积的长度

    char *res = (char *)malloc(sizeof(char) * (cnt + 1)); //分配内存,考虑到有字符串结尾,多分配一个字节。
    res[cnt--] = '\0'; //字符结尾

    int c = 0;
    while (cnt >= 0) {
        int sum = 0;
        for (int i = len_a - 1; i >= 0; i--) {
            if (cnt - i < 0 || cnt - i >= len_b) {  //保证b数组索引的有效性
                continue;
            }
            sum += (a[i] - '0') * (b[cnt - i] - '0'); //记录该次的和
        }
        sum += c;  //加上上次进位
        c = sum / 10;  //计算本次进位
        res[cnt--] = sum % 10 + '0';  //计算本次应该保存的数字
    }

    return res;
}
这里只是最基本的卷积方法,如果位数较多,可以采用比如DFT快速傅里叶变换的方法等,博主水平有限,尚未进一步优化。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值