C语言大数相加实现方法分析

原创 2018年04月16日 16:01:36

使用C语言内置的int,在32位系统下最大只能表示2^31-1,也就是2147483647,想要表示更大的数可以使用字符串。

下面是楼主实现字符串数字相加的分析过程:

1.首先来个简单的,单个数字字符相加求和

inline int addchar(char c1,char c2,char &s){
	int t=c1+c2;
	//0-9的ascii码是48-57
	if(t<106){//5的ascii码是53,小于106说明相加不超过10
		s=(char)(t-48);//返回对应数字的char
		return 0;
	}else{
		s=(char)(t-58);//再多减去10
		return 1;
	}
}

这个函数肯定会经常被调用,所以加上inline,最后一个参数保存相加结果的最后一位,如果有进位返回1,否则返回0。

测试一下发现没有问题,我们继续分析。

最基础的1位加法功能写好了,接下来就只要按照外面小学时学的加法计算方法把每一位一个个相加即可。

2.先写个简单的情况:假设计算过程中没有进位并且2个求和的字符串长度相等,比如1122+2233,结果应该是3355

函数定义

void bignumadd(const char* num1,const char* num2,char* sum){//大数相加
}

第一步先要获取输入字符串的长度,然后开始遍历,当然要从最后一位往前遍历一个个相加,保存结果的时候,由于不知道最后结果到底有多少,所以我们可以倒着放(第一位放个位相加结果,第二位放十位相加结果...),最后逆向输出一下即可

比如最后结果等于3355,那么sum={'5','5','3','3',0,0,0,0}

所以函数是这样的

void bignumadd(const char* num1,const char* num2,char* sum){//大数相加
	size_t len1=strlen(num1);//得到输入字符串长度,这里假设2个数字是一样长的
	for(size_t i=0;i<len1;++i){//遍历每个字符
		//注意计算的时候从最后一位开始,保存的时候从第一位开始
		addchar(num1[len1-i-1],num2[len1-i-1],sum[i]);
	}
}

输出结果的函数

void showsum(const char* s){//显示计算结果
	size_t len=strlen(s);
	for(int i=len-1;i>-1;--i){//从最后一位开始逆序输出
		putchar(s[i]);
	}
}

接着我们在主函数里面测试一下

int main() {
	const char* num1="1122";
	const char* num2="2233";
	char s[100]={0};//分配100字节的栈空间存放结果
	printf("%s+%s\n=",num1,num2);
	bignumadd(num1,num2,s);
	showsum(s);
	getchar();
	return 0;
}

看到输出为

1122+2233

=3355

验证通过

3.然后再来个稍微复杂点的,还是不进位,但是2个数的长度不一定相同

当遍历完短的字符串之后,长的字符串高位剩下部分每一位直接和0相加即可,代码如下

void bignumadd(const char* num1,const char* num2,char* sum){//大数相加
	size_t len1=strlen(num1),len2=strlen(num2),i=0;//得到输入字符串长度
	if(len1>len2){//如果第一个字符串长
		for(;i<len2;++i){//len2比较小,先遍历完
			addchar(num1[len1-i-1],num2[len2-i-1],sum[i]);
		}
		for(;i<len1;++i){//剩下部分
			addchar(num1[len1-i-1],'0',sum[i]);//第一个字符串多出来的直接和0加
		}
	}else{//如果第二个字符串长
		for(;i<len1;++i){//len1比较小,先遍历完
			addchar(num1[len1-i-1],num2[len2-i-1],sum[i]);
		}
		for(;i<len2;++i){//剩下部分
			addchar('0',num2[len2-i-1],sum[i]);//第二个字符串多出来的直接和0加
		}
	}
}

然后在主函数里面把num1改为111,结果是2344,再把num2改成5,结果是116,说明没问题

4.接下来我们就可以考虑带进位的了,按照加法的计算规则,进位要加到高位上去,因此用一个变量保存一下这位相加的时候有没有进位,下次再加上1就好了,为了方便,我们给最开始的1位加法做个小改动,给它添加一个参数

inline int addchar(char c1,char c2,int f,char &s){//带进位字符加法
	int t=c1+c2+f;
	//0-9的ascii码是48-57
	if(t<106){//5的ascii码是53,小于106说明相加不超过10
		s=(char)(t-48);//返回对应数字的char
		return 0;
	}else{
		s=(char)(t-58);//再多减去10
		return 1;
	}
}

f表示是否需要进位,最终的计算结果再加上f就行了

然后我们在计算的时候就可以很方便地处理进位了,代码如下

void bignumadd(const char* num1,const char* num2,char* sum){//大数相加
	size_t len1=strlen(num1),len2=strlen(num2),i=0;//得到输入字符串长度
	int f=0;//用于保存进位,第一次计算个位的时候进位肯定是0
	if(len1>len2){//如果第一个字符串长
		for(;i<len2;++i){//len2比较小,先遍历完
			f=addchar(num1[len1-i-1],num2[len2-i-1],f,sum[i]);
		}
		for(;i<len1;++i){//剩下部分
			f=addchar(num1[len1-i-1],'0',f,sum[i]);//第一个字符串多出来的直接和0加
		}
	}else{//如果第二个字符串长
		for(;i<len1;++i){//len1比较小,先遍历完
			f=addchar(num1[len1-i-1],num2[len2-i-1],f,sum[i]);
		}
		for(;i<len2;++i){//剩下部分
			f=addchar('0',num2[len2-i-1],f,sum[i]);//第二个字符串多出来的直接和0加
		}
	}
	//别忘记最高位还可能会进位
	for(;f>0;++i){
		f=addchar('0','0',f,sum[i]);
	}
}

重点就是addchar了,将上一次的进位结果也进行计算,同时保存本次进位结果

最后遍历完成的时候最高位还可能会有进位,别忘记处理了

然后我们在主函数中测试一下

num1=87,num2=9999,结果是10086,正确

是不是很简单O(∩_∩)O

下面是所有完整源代码

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

inline int addchar(char c1,char c2,int f,char &s){//1位加法,f表示进位
	int t=c1+c2+f;
	if(t<106){
		s=(char)(t-48);
		return 0;
	}else{
		s=(char)(t-58);
		return 1;
	}
}
void bignumadd(const char* num1,const char* num2,char* sum){//大数相加
	size_t len1=strlen(num1),len2=strlen(num2),i=0;//得到输入字符串长度
	int f=0;//用于保存进位
	if(len1>len2){//如果第一个字符串长
		for(;i<len2;++i){//len2比较小,先遍历完
			f=addchar(num1[len1-i-1],num2[len2-i-1],f,sum[i]);
		}
		for(;i<len1;++i){//剩下部分
			f=addchar(num1[len1-i-1],'0',f,sum[i]);//第一个字符串多出来的直接和0加
		}
	}else{//如果第二个字符串长
		for(;i<len1;++i){//len1比较小,先遍历完
			f=addchar(num1[len1-i-1],num2[len2-i-1],f,sum[i]);
		}
		for(;i<len2;++i){//剩下部分
			f=addchar('0',num2[len2-i-1],f,sum[i]);//第二个字符串多出来的直接和0加
		}
	}
	//别忘记最高位还可能会进位
	for(;f>0;++i){
		f=addchar('0','0',f,sum[i]);
	}
}
void showsum(const char* s){//显示计算结果
	size_t len=strlen(s);
	for(int i=len-1;i>-1;--i){//从最后一位开始逆序输出
		putchar(s[i]);
	}
}
int main() {
	const char* num1="87";
	const char* num2="9999";
	char s[100]={0};//分配100字节的栈空间存放结果
	printf(" %s+%s\n=",num1,num2);
	bignumadd(num1,num2,s);
	showsum(s);
	getchar();
	return 0;
}

这样就完成了大正整数的加法,减法和负数也是同样的思路,有兴趣的兄弟可以自己改改试试

楼主技术有限,要是有什么不好的地方欢迎指出哈

转载请注明出处https://blog.csdn.net/rtduq/article/details/79954816

软件复用为软件开发提速

软件复用为软件开发提速四木(本文转载自软件工程专家网www.21cmm.com)    随着社会信息化程度的提高,IT技术已经深入到社会生活的方方面面,而软件作为IT技术应用的核心,其重要性也日渐突出...
  • gigix
  • gigix
  • 2002-04-09 09:37:00
  • 1390

C语言实现大数相加相减和相乘

C语言 大数相加 大数相减 大数相乘
  • linaijunix
  • linaijunix
  • 2015-12-20 16:42:27
  • 2031

C语言:大数相加与大数相减.

#include #include #define N 100 int res[N] = {0}; char *add(char a[], int n, char b[], int m) //...
  • lky199598
  • lky199598
  • 2014-07-19 22:19:41
  • 3124

大数相加原理以及代码(C)

因为C语言里面的int型范围只是32位,所以有时候对于大数很难进行相加,因为会溢出。所以这时候我们可以将大数以字串的形式表示,然后将其变形保存在数组里面。接着对数组进行个位数相加,从最低位开始,所产生...
  • qq_30035873
  • qq_30035873
  • 2016-04-21 21:24:37
  • 952

用线性链表实现大数相加(c语言)[初学者]

1题目描述设计算法完成两个超长正整数的加法运算。2 问题分析与算法设计看到加法运算,首先想到c提供的加法运算符。呵呵,这还不简单吗?题目不会如此弱智吧?再看看,注意到“超长正整数”,超长?!多长的算超...
  • flowhat
  • flowhat
  • 2005-12-05 16:07:00
  • 3295

C语言超大数相加

#include #include void reverse(char *s,int len); char * addLargeNumber(char *s1,char *s2); int...
  • hanangellove
  • hanangellove
  • 2015-01-07 08:54:46
  • 7977

用C语言编写两个大数相加

  • 2013年01月02日 11:16
  • 6KB
  • 下载

链表实现大数相加和大数相乘

全部c代码如下#include #include #define ElemType int#define HUNTHOU 10000typedef struct LNode  //链表节点{ Elem...
  • flowhat
  • flowhat
  • 2005-12-20 11:37:00
  • 2341

大数系列——大数加法

这几天专门学习了一下大数的有关计算方法,大数加减乘除模都会在后面讲到。 一、大数加法: 加法算是最简单的一类大数问题,先写上我的代码: #include #include using namespac...
  • sinyusin
  • sinyusin
  • 2016-08-21 19:20:04
  • 950

C 语言 超大数相加和求余

超大数相加 这里超大数表示已经超出int、long、long long 范围的数字,所以不能简单的相加。此时就要用字符串,把输入的内容储存在字符串中,通过字符与数字之间的关系计算结果。 思路: ...
  • hanangellove
  • hanangellove
  • 2015-04-11 19:30:30
  • 5219
收藏助手
不良信息举报
您举报文章:C语言大数相加实现方法分析
举报原因:
原因补充:

(最多只允许输入30个字)