用字符数组实现大数相加

第一种逻辑比较直接但是过程略显冗杂的方法

思想

  1. 由于最长整形无法存入大数,所以选用字符数组来存放输入的数字,输入之后会像这样:
999999       ——first_add
88888        ——second_add
  1. 用两个变量记录两个加数的长度,比较并记录最大长度

  2. 直接从两个加数的个位开始向前遍历相加,并将结果退一位记录在另一个字符数组中,比如这样:
    在这里插入图片描述

代码拆分

由于这种方法重点在于模拟竖式加法,且在两个加数不等长的讨论中,思路是一样的,所以只对其中一种情况做详解。

for (i = 0; i < len_max; i++) {
	if (i < len_second) {
		//较短加数还没遍历完时
		j = first_add[len_first - i - 1] + second_add[len_second - i - 1] - 96 + flag;
		//直接将上一位的进位结果与当前位相加,但是记得flag要初始化为0
		if (j >= 10) {
			flag = 1;
			j %= 10;

		}
		else {
		/*这个else必须存在,不然会导致进位结果过度顺延,因为当前位的结果
		要顺延至下一位,所以不能用每一轮循环后重置来代替这个else的作用*/
			flag = 0;
		}
	}
	else {
		//较短加数遍历完了,只用计算进位和较长加数
		j = first_add[len_first - i - 1] + flag;
		if (j >= 10) {
			flag = 1;
			j %= 10;
		}
		else {
			flag = 0;
		}
	}
	result[len_max - i] = j + 48;
	//要记得把结果转化为字符再存入字符数组里面
}
result[len_max + 1] = '\0';
//记得字符串最后要加终止符,不然后面用 %s输出会有乱码

完整代码

#include<stdio.h>
#include<string.h>
//假设数字最大位数时是200位
int main(void) {
    char first_add[200];
    char second_add[200];
    char result[201];
  	int len_first = 0, len_second = 0, len_max = 0;
	int i = 0, flag = 0,j = 0;//flag作为进位标志,j储存每一位加法和
	scanf("%s", first_add);
	scanf("%s", second_add);
	len_first = strlen(first_add);
	len_second = strlen(second_add);
	if (len_first > len_second) {
		//如果第一个加数比第二个大
		len_max = len_first;
		for (i = 0; i < len_max; i++) {
			if (i < len_second) {
				//较短加数还没遍历完时
				j = first_add[len_first - i - 1] + second_add[len_second - i - 1] - 96 + flag;
				if (j >= 10) {
					flag = 1;
					j %= 10;

				}
				else {
					flag = 0;
				}
			}
			else {
				//较短加数遍历完了,只用计算进位和较长加数
				j = first_add[len_first - i - 1] + flag;
				if (j >= 10) {
					flag = 1;
					j %= 10;
				}
				else {
					flag = 0;
				}
			}
			result[len_max - i] = j + 48;
			//要记得把结果转化为字符再存入字符数组里面
		}
		result[len_max + 1] = '\0';
		if (flag) {
			result[0] = '1';
			printf("%s", &result[0]);
		}
		else {
			printf("%s", &result[1]);
		}
	}
	else {
	//以下的思路与上面是一样的,只是由于 first_add和 second_add的长度不一样,在计算时做了区分
		len_max = len_second;
		for (i = 0; i < len_max; i++) {
			if (i < len_first) {
				j = first_add[len_first - i - 1] + second_add[len_second - i - 1] - 96 + flag;
				if (j >= 10) {
					flag = 1;
					j %= 10;
				}
				else {
					flag = 0;
				}
			}
			else {
				j = second_add[len_second - i - 1] + flag;
				if (j >= 10) {
					flag = 1;
					j %= 10;
				}
				else {
					flag = 0;
				}
			}
			result[len_max - i] = j + 48;
		}
		result[len_max + 1] = '\0';
		if (flag) {
			result[0] = '1';
			printf("%s", &result[0]);
		}
		else {
			printf("%s", &result[1]);
		}
	}
    return 0;
}
}

第二种逻辑更为直接但是步骤非常多的方法

思想

  1. 由于最长整形无法存入大数,所以选用字符数组来存放输入的数字,输入之后会像这样:
999999       ——first_add
88888        ——second_add
  1. 考虑到进位的问题,所以将字符数组向右对齐并退一位,达到这样的效果:
 0999999      	 ——first_add
 0088888     	 ——second_add
  • 考虑进位,相加,于是结果就变成这样:
 	 0999999      	 ——first_add
 -   0088888     	 ——second_add
-------------
     1088887		 ——result

代码拆分

  • 把两个字符串右对齐
//无论是不是最长字符串,都要往后挪一位,为结果的进位腾出位置
	//first_add
	for (i = 0; i <= len_max; i++) {
		if (i < len_first) {
		//这里不能取等号,否则会导致下一步赋值出现问题
			first_add[len_max - i] = first_add[len_first - i - 1];
			/*这里相当于把原字符串的倒数第i个字符,赋给最长字符串从后往前数第i个位置,
			由于原字符串最后一位是'\0'所以还要减一才能够取到有效字符*/
		}
		else {
			first_add[len_max - i] = '0';
			//将后移之后的字符串,前面补足0
		}
	}
	first_add[len_max + 1] = '\0';

	//second_add
	for (i = 0; i <= len_max; i++) {
		if (i < len_second) {
			second_add[len_max - i] = second_add[len_second - i - 1];
		}
		else {
			second_add[len_max - i] = '0';
		}
	}
	second_add[len_max + 1] = '\0';
  • 模拟竖式加法运算
    (悄咪咪说一下,数字’0’的ASCII码是48)
for (i = len_max; i >= 0; i--) {
		j = (first_add[i] - 48) + (second_add[i] - 48) + flag;
		//注意flag在这步之前一定要初始化成0,否则个位相加就会出错
		if (j >= 10) {
			flag = 1;
			j %= 10;
		}
		else {
			flag = 0;
		}
		result[i] = j  + 48;
	}
  • 输出结果
	result[len_max +1] = '\0';
	//记得要补一个终止符,不然不会自动停喔
	if ('0' == result[0]) {
		printf("%s", &result[1]);
	}
	else {
		printf("%s", &result[0]);
	}
	//通过判断最大位是否有进位,决定从第几个字符开始输出

完整代码

#include<stdio.h>
#include<string.h>
int main(void) {
	char first_add[201];
	char second_add[201];
	char result[201];
	//考虑到进位的问题,要比加数中最大的还要多一位
	int len_first = 0, len_second = 0, len_max = 0;
	int i = 0, flag = 0,j = 0;//flag作为进位标志,j储存每一位加法和
	scanf("%s", first_add);
	scanf("%s", second_add);
	len_first = strlen(first_add);
	len_second = strlen(second_add);
	len_max = len_first > len_second ? len_first : len_second;
	
	//无论是不是最长字符串,都要往后挪一位,为结果的进位腾出位置
	//first_add
	for (i = 0; i <= len_max; i++) {
		if (i < len_first) {
			//没有等于号
			first_add[len_max - i] = first_add[len_first - i-1];
		}
		else {
			first_add[len_max - i] = '0';
		}
	}
	first_add[len_max + 1] = '\0';

	//second_add
	for (i = 0; i <= len_max; i++) {
		if (i < len_second) {
			second_add[len_max - i] = second_add[len_second - i-1];
		}
		else {
			second_add[len_max - i] = '0';
		}
	}
	second_add[len_max + 1] = '\0';
	
	//从max位开始向前做加法
	for (i = len_max; i >= 0; i--) {
		j = (first_add[i] - 48) + (second_add[i] - 48) + flag;
		if (j >= 10) {
			flag = 1;
			j %= 10;
		}
		else {
			flag = 0;
		}
		result[i] = j  + 48;
	}
	result[len_max +1] = '\0';
	if ('0' == result[0]) {
		printf("%s", &result[1]);
	}
	else {
		printf("%s", &result[0]);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值