大数加减乘法以及阶乘求解

目录

一、大数加法

二、大数减法

三、大数乘法

四、阶乘计算(例如66!)


一、大数加法

#include<stdio.h>
#include<string.h>
/*大数加法 
	大数是存放在字符数组里的,毫无疑问,如果两个数位数不一样
	要实现个十百位对齐  因此 1、得实现两个字符数组逆序存放
	2、存放好后相应位数相加(字符相加会怎么样,如何处理) 并且处理进位 
//若c[i]=a[i]+b[i];
//字符相加,做的实际上是整数运算,例如'1'+'9'对应ascii是49+57 
//直接用字符去相加较为麻烦,最好可以接一个桥梁中间站 即整型的 va vb vc 
//把当前字符数组的字符元素转换成数字再相加  
*/
void bigsum(char *a,char *b,char *c);
void ni(char *a);
void swap(char *a,char*b);

int main(void)
{	
	int i;
	char a[201];
	char b[201];
	char c[201];
	scanf("%s",a);
	scanf("%s",b);
	//1 逆序存放 对齐位数 
	ni(a);
	ni(b);
	//2 对应位数相加 对于哪个字符串的位数更多,用lenc来解决
	bigsum(a,b,c);
	//3 逆序输出
	ni(c); 
	for(i=0;i<strlen(c);i++){
		printf("%c",c[i]);
	} 
}
void ni(char *a){
	int len=strlen(a);
	int i;
	for(i=0;i<len/2;i++){
		swap(&a[i],&a[len-i-1]);
	}
}
void bigsum(char *a,char *b,char *c){
	int i;
	int lena=strlen(a);
	int lenb=strlen(b);
	int lenc=lena>lenb?lena:lenb; 
	int x=0;//进位的数目 
	int va=0,vb=0,vc=0; 
	for(i=0;i<lenc;i++){
		//这时又有一个问题,如果一个数组已经计算完位数了,后面是'\0',而另外一个数还没到尽头
		//如果还是让va=a[i]-'0' 如果a[i]是'\0' 对应ascii是0 则会导致va=0-48=-48。故需要用加一个判断 
		va=i<lena?a[i]-'0':0;	//字符型转换为整型数字 
		vb=i<lenb?b[i]-'0':0;
	//当前i是否还是小于lena或lenb的?是 则还有数字,可以用其相减,否则应该让va或vb=0 
		vc=va+vb+x;
		//把ab数组的字符变成数字,方便于在c处相加 
		if(vc>=10){
			vc=vc%10;	//如果vc大于10.计算vc剩下的个位数 
			c[i]=vc+'0';
			x=1;		//计算进位 
		} else{
			x=0; 
			c[i]=vc+'0';//整型数字转换为字符型 
		}
	}
	//循环结束后,还需要判断进位标志x是否为0,若不为0,
	//说明最后一次加和也大于0,但是由于i=lenc了,恰好在c[lenc]处设置为'1' 
	if(x!=0){
		c[lenc]='1';
	}
}
void swap(char *a,char*b){
	char c;
	c=*a;
	*a=*b;
	*b=c;
}

二、大数减法

#include<stdio.h>
#include<string.h>
void swap(char* a,char* b){
	char c;
	c=*a;
	*a=*b;
	*b=c;
}
void ni(char* a){
	int i;
	int len=strlen(a);
	for(i=0;i<len/2;i++){
		swap(&a[i],&a[len-1-i]);
	}
}
void bigminus(char* a,char* b,char* c){
	int lena,lenb,lenc;
	int va,vb,vc;
	int x=0;
	int i; 
	lena=strlen(a);
	lenb=strlen(b);	
	
	for(i=0;i<lena;i++){
		va=a[i]-'0';
		vb=i<lenb?b[i]-'0':0;
		
		vc=va-vb-x;
		if(vc<0){
			x=1;
			c[i]=vc+10+'0';
		}else{
			x=0;
			c[i]=vc+'0';
		}
	}
}

int main(void){
	int i;
	char a[201];
	char b[201];
	char c[201];
	scanf("%s",a);
	scanf("%s",b);
	ni(a);
	ni(b);
	bigminus(a,b,c);
	ni(c); 
	for(i=0;i<strlen(c);i++){
		printf("%c",c[i]);
	} 
} 

三、大数乘法

#include<stdio.h>
#include<string.h>
void swap(char* a,char* b){
	char c;
	c=*a;
	*a=*b;
	*b=c;
}
void ni(char* a){
	int i;
	int len=strlen(a);
	for(i=0;i<len/2;i++){
		swap(&a[i],&a[len-1-i]);
	}
}
void mult(char* a,char* b,char* c){
	int i,j;
	int x; 
	int lena,lenb;
	lena=strlen(a);
	lenb=strlen(b);
	int va=0,vb=0,vc=0;	
//因为乘法是 b数的个位乘以 a数的个位、十位、百位等等,b数的十位乘以a数的个位、十位、百位等等,以此类推 
//因此需要嵌套循环 	
	for(i=0;i<lenb;i++){		 
		x=0;
		for(j=0;j<lena;j++){	
			va=a[j]-'0';
			vb=b[i]-'0';//把每一位的字符变成数字! 
			
			if(c[i+j]!=0){//预防操作:a数的j位乘以b数的i位,最多到达c数的i+j位  因此需要检查i+j位是否不为0 
				vc=c[i+j]-'0';
			}else{
				vc=0;
			} 
			
			vc=va*vb+x+vc;
			x=vc/10;	//进位数 
			c[i+j]=vc%10+'0';  //数字变字符 
			//为什么一定是i+j位呢?
			/*我们来思考一下,	第一轮i=0,c[i+j]相当于在0的基础上只决定于 j 
								第二轮 i=1,相当于在1的基础上只决定于j 
								第三轮 i=2,相当于在2的基础上只决定于j
					例如 1234x5678  1234:a数 5678:b数
						1234		a数 
					x	5678		b数 
					----------
						9872        结果占据数组的0123位    第一轮 i=0指向8  j=0-3内层循环从4到1	 
					   8538			结果占据数组的1234位	第二轮 i=1指向7	 j=0-3内层循环从4到1						
					  7404			结果占据数组的2345位	第三轮 i=2指向6  j=0-3内层循环从4到1 
					 6170	 		结果占据数组的3456位	第四轮 i=3指向5	 j=0-3内层循环从4到1
	写到这里应该知道为什么是c[i+j] 
	*/
		}
		if(x>0){
			c[i+lena]=x+'0';
		}
	}
} 
int main(void){
	int i; 
	char a[201]={0};
	char b[201]={0};
	char c[402]={0};
	scanf("%s",a);
	scanf("%s",b);	
	ni(a);
	ni(b);
	mult(a,b,c);
	ni(c);
	for(i=0;i<strlen(c);i++){
		printf("%c",c[i]);
	} 
}

四、阶乘计算(例如66!)

#include<stdio.h>
#include<string.h>
void swap(char* a,char* b){
	char c;
	c=*a;
	*a=*b;
	*b=c;
}
void ni(char* a){
	int i;
	int len=strlen(a);
	for(i=0;i<len/2;i++){
		swap(&a[i],&a[len-1-i]);
	}
}

//数组和 k 相乘 
void multi(char* a,int k){
	int i;
	int len;
	int v=0;//表示数组当前位置的数与乘数k乘法结果 
	int x=0;
	len=strlen(a);
	for(i=0;i<len;i++){
		v=(a[i]-'0')*k+x;
		x=v/10;
		a[i]=v%10+'0';
	} 
	//遍历结束后,但可能x中的值不为0,仍需要在数组向前填充 
	while(x>0){
		a[len]=x%10+'0';
		len++;
		x=x/10; 
	} 
	//循环数组的每一位数字,计算当前位置的数字与乘数的乘法结果 
}

int main(void){
	char a[35661]={0};
	int i; 
	int n;
	scanf("%d",&n);
	a[0]='1'; 
	
	for(i=1;i<=n;i++){
		multi(a,i);
	}	// 循环 数组的数不断与i相乘,得到阶乘 
	
	ni(a);
	for(i=0;i<strlen(a);i++){
		printf("%c",a[i]);
	} 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值