算法 大数相加 C/C++ 实现

问题

如果相加的两个数位数过多,大于32位(int),大于64位(long),该如果计算?

解决方法

可以用两个字符数组去储存两个大数,然后就是字符相加

具体细节

先拿出草稿,默默的用两个大数,竖式算一遍,然后记住这个过程中过的细节,再转换为代码(也可以先看代码部分,代码部分有详细注释):

  1. 低位开始相加
    转换成代码思维:两个数组保存的数都是低索引保存高位,因此两种方法,一种先把两个数组反转,一种就是从数组最后一位开始计算
  2. 有进位
    在计算的过程中,如果低位相加大于10,需要把结果的余数作为此次结果,除以10的结果作为进位,此进位下次和高位的数相加。
  3. 两个数组的长度不一致
    在计算的过程中是两个数组对应位数的数再加上进位,如果加数已经加完了,那么就是被加数和进位相加就可以了
  4. 结果需要反转
    如果计算的过程中低位相加的结果放在结果数组的低索引中,最后需要把结果反转。

代码实现

#include <iostream>

//字符数组反转 
void reverseStr(char a[], int len_a) {
    int mid = len_a / 2;

    int i = 0, j = len_a - 1;
    char t;

//最后一位和第一位交换,倒数第二位和第二位交换.....
    for (int k = 0; k < mid; k++) {
        t = a[i];
        a[i] = a[j];
        a[j] = t;
        i++;
        j--;
        
    }
}

//字符数组相加
void strAdd(char output[],char a[], int len_a, char b[], int len_b) {
 // i 为加数 a[]的最后一位,j为被加数 b[]的最后一位
    int i = len_a - 1, j = len_b - 1;  
//c表示进位,个数相加的时候,进位是0
    int c = 0;
    int sum = 0;
    int k = 0;

//结果的位数为(len_a,len_b)中最大的数值或者此数值+1
    for (k = 0; k < len_a||k<len_b; k++) {
        sum = 0;
        if (k < len_a) {
         //先-‘0’ 变为int型,加上 加数
            sum += a[i] - '0'; 
            i--;
        }

        if (k < len_b) {
        // -‘0’变为int型,加上被加数
            sum += b[j] - '0'; 
            j--;
        }
        //加上进位
        sum += c;    
        //获取下一次计算的进位      
        c = sum / 10;
        //获取此位置上的数值结果,+‘0’ 从int型变为字符型
        output[k] = sum % 10 + '0';

        printf("temp[%d]=%c ", k, output[k]);
    }

// 最后c 为1,结果数值为max(len_a,len_b)+1
    if (c == 1) {
       //这个1需要
        output[k] = '1';
        //字符数组的最后加上'\0'
        output[k + 1] = '\0';
        //最后结果反转
        reverseStr(output, k + 1);
    }
    // 最后c 为0,结果数值为max(len_a,len_b)
    else {
      //字符数组的最后加上'\0'
        output[k] = '\0';
      //字符数组的最后加上'\0'  
        reverseStr(output, k);
    }
  
}


int main()
{
    char result[1000];
    char str1[100] = { '3','5','8','7','9','1'};
    char str2[100] = { '5','9','9','6','5','5','7'};
    
    strAdd(result,str1, 6, str2,7);
    char* str3 = result;

    while (*str3 != '\0') {
        printf("%c", *str3);
        str3++;
    }
    printf("\n");

    return 0;
}

运行结果

运行结果截图

调式注意的地方

1, 代码中i,j,k的数值变化是否正确
2. 加数和被加数都加完了,是否考虑了最后一次的进位
3. 在相加的时候是否转成了int型,结果是否转回成字符型

代码实现技巧

  1. 每次不是加数+被加数+进位一起加,而是判断,如果加数没有加完,加上;如果被加数没有加完,加上;
  2. 加数和被加数刚开始没有反转,而是从最后一位开始

总结

 大数加法,大数减法,大数乘法,大数除法这些都没有用到什么特别的算法或者想不到的技巧,更考验算法的基本功。做算法千万不能看一眼,感觉会了就可以了;需要自己练,敲代码,调式出来了,还有以后碰到这个可以很快的写出来,这样就是会了。

写在最后的话

这段时间碰到的那些人那些事:
1. 某天打滴滴顺风车,同行的是一位做医疗器械公司的员工。同行者聊了起来: 说她们公司之前欠几个亿,这段时间由于呼吸机急需,她们公司赚了几个亿,然后上市了,员工福利待遇也提高了,越说越嗨。
2. 某天打滴滴顺丰车,顺风车司机是做外贸(出口服装)公司的员工。聊了起来:现在她们每个月可以拿到三千多的基本工资,五险一金以最少的标准,公司帮忙交。公司鼓励她们出去赚赚钱,然后她就开起了滴滴顺风车;然后回忆起她们公司以前的光景。
 每次静静的听着,听着她们的故事,仿佛跟着她们的思绪快速的走了一遍她们的生活,感受着她们的开心与失落~~
 也许人生无常,过好每一天,做好每一天想做的事,吃好想吃的食物,甚好~~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猫 猫小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值