问题
如果相加的两个数位数过多,大于32位(int),大于64位(long),该如果计算?
解决方法
可以用两个字符数组去储存两个大数,然后就是字符相加
具体细节
先拿出草稿,默默的用两个大数,竖式算一遍,然后记住这个过程中过的细节,再转换为代码(也可以先看代码部分,代码部分有详细注释):
- 低位开始相加
转换成代码思维:两个数组保存的数都是低索引保存高位,因此两种方法,一种先把两个数组反转,一种就是从数组最后一位开始计算 - 有进位
在计算的过程中,如果低位相加大于10,需要把结果的余数作为此次结果,除以10的结果作为进位,此进位下次和高位的数相加。 - 两个数组的长度不一致
在计算的过程中是两个数组对应位数的数再加上进位,如果加数已经加完了,那么就是被加数和进位相加就可以了 - 结果需要反转
如果计算的过程中低位相加的结果放在结果数组的低索引中,最后需要把结果反转。
代码实现
#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型,结果是否转回成字符型
代码实现技巧
- 每次不是加数+被加数+进位一起加,而是判断,如果加数没有加完,加上;如果被加数没有加完,加上;
- 加数和被加数刚开始没有反转,而是从最后一位开始
总结
大数加法,大数减法,大数乘法,大数除法这些都没有用到什么特别的算法或者想不到的技巧,更考验算法的基本功。做算法千万不能看一眼,感觉会了就可以了;需要自己练,敲代码,调式出来了,还有以后碰到这个可以很快的写出来,这样就是会了。