如何实现大整数相加?

当我们两个100位的整数相加时,该如何处理?

由于大于Long的表示范围,因此不能用Long来表示,只能用数组来表示

然后像做小学数学题一样做运算

详细步骤:

第一步,把整数倒序存储,整数的个位存于数组0下标位置,最高位存于数组长度-1下标位置。之所以倒序存储,更加符合我们从左到右访问数组的习惯。

第二步,创建结果数组,结果数组的最大长度是较大整数的位数+1,原因很明显。

第三步,遍历两个数组,从左到右按照对应下标把元素两两相加,就像小学生计算竖式一样。

例子中,最先相加的是数组A的第1个元素8和数组B的第1个元素9,结果是7,进位1。把7填充到Result数组的对应下标,进位的1填充到下一个位置:

第二组相加的是数组A的第2个元素1和数组B的第2个元素2,结果是3,再加上刚才的进位1,把4填充到Result数组的对应下标:

第三组相加的是数组A的第3个元素3和数组B的第3个元素1,结果是4,把4填充到Result数组的对应下标:

第四组相加的是数组A的第4个元素2和数组B的第4个元素3,结果是5,把5填充到Result数组的对应下标:

以此类推......一直把数组的所有元素都相加完毕:

第四步,把Result数组的全部元素再次逆序,去掉首位的,就是最终结果:

实例代码:

加数和被加数时逆序,和时正序

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

int fun(char* str1, char *str2, char *str_add)
{
	int i;
	int temp = 0;
	char is_zeor = 0;

	int max_len = strlen(str1) > strlen(str2) ? strlen(str1)+1:strlen(str2)+1;
	char *array_str1 = malloc(max_len);
	char *array_str2 = malloc(max_len);
	char *array_add = malloc(max_len);	
	
	//printf("[%d] [%d] [%d] \n", max_len, strlen(str1), strlen(str2));
	if((array_add == NULL) || (array_str1 == NULL) || (array_str2 == NULL)){
		return -1;
	}
	memset(array_str1, 0, max_len);
	memset(array_str2, 0, max_len);
	memset(array_add, 0, max_len);

	for(i = 0; i < strlen(str1); i++){
		array_str1[i] = str1[i] - '0';		
	}
	array_str1[i] = '\0';
	for(i = 0; i < strlen(str2); i++){
		array_str2[i] = str2[i] - '0';		
	}
	array_str2[i] = '\0';
/*
	for(i = 0; i < max_len; i++){
		printf("<%c>\n", array_add[i] + '0');		
	}
*/	
	for(i = 0; i < max_len; i++){
		temp = (int)array_add[i];
		temp += (int)array_str1[i];
		temp += (int)array_str2[i];
		
		if(temp >= 10){
			temp = temp -10;
			array_add[i+1] = 1;
		}
		array_add[i] = temp;
	}
/*调试
	for(i = 0; i < max_len; i++){
		printf("[%c]\n", array_add[i] + '0');		
	}

	printf("num = %d\n", array_add[max_len - 1]);
*/
	if(array_add[max_len - 1] == 0){
		is_zeor = 1;
	}	
	for(i = 0; i < max_len; i++){
		if(is_zeor == 1){
			if(i == 0){
				continue;
			}else{
				str_add[i - 1] = array_add[max_len - 1 -i] + '0';
			}	
		}else{
			str_add[i] = array_add[max_len - 1 -i] + '0';
		}
	}
	if(is_zeor == 0){
		str_add[i - 2] = '\0';		
	}else{
		str_add[i - 1] = '\0';			
	}

	return 0;
}


int main()
{
	int i;
	char str1[10] = {"111"};
	char str2[10] = {"22223"};
	char str_add[10] = {0};
	
	fun(str1, str2, str_add);
	
	printf("[%s] + [%s] = [%s]\n", str1, str2, str_add);	
	return 0;
}

运行结果:

[111] + [22223] = [32333]

如何优化呢?

我们之前是把大整数按照每一个十进制数位来拆分,比如较大整数的长度有50位,那么我们需要创建一个51位的数组,数组的每个元素存储其中一位。

我们真的有必要把原整数拆分得那么细吗?显然不需要,只需要拆分到可以被直接计算的程度就够了。

int类型的取值范围是 -2147483648——2147483647,最多有10位整数。为了防止溢出,我们可以把大整数的每9位作为数组的一个元素,进行加法运算。(这里也可以使用long类型来拆分,按照int范围拆分仅仅是提供一个思路)

如此一来,占用空间和运算次数,都被压缩了9倍。

参考:

https://mp.weixin.qq.com/s?__biz=MzA5MzY4NTQwMA==&mid=2651007250&idx=1&sn=d98fa4b3e30bd61ff77e980f361447b8&chksm=8bad9ae5bcda13f319f3d614963f82cb18691539cd4ca6949a546e43934075f444d304c69a7a&mpshare=1&scene=23&srcid=1202wH7VGPdEt8bkUbl5Jz3k#rd

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值