大数四则运算

       前一章将遇到了A+B>C的问题,具体如下:给定区间[-2^31^, 2^31^]内的3个整数A、B和C,请判断A+B是否大于C。因为范围只有2^32,所以可以用long long 或者double 解决,可问题来了,要是数据大于2^63-1,怎么办?8个字节处理不了。这个时候就必须自己构造一种数据类型来存放该数。下面分析一下大数的数据类型该如何定义(个人心得,有更好的方法欢迎互相交流):

1、首先想到的是链表与数组,可是链表有一个问题,那就是太“灵活”了,数据的长度可以随时改变,不好处理。因此,必须使大数的数据长度是固定的。我选择了字符串数组,为什么不用int 数组呢?没必要,浪费内存;当然也可以使用。

2、然后就得定义大数高位、低位在数组中存放的方式了,我选择的是高位在高字节、低位在低字节。同时高位补零‘0’,还有不能忘了字符串最后一位定义为‘\0’。

 3、由于上述定义不能通过字符串函数输出,因此需要先确定长度,再输出,需要定义返回长度的函数。

 4、加法运算,减法运算、乘法运算如果不是正整数,必须需要判断正负,再写出正整数的加减乘函数即可。注意函数不能返回,只能通过形参传递。

具体实现:

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

#define Length 5*8+1
void LInput(char *a);   /* 大数输入 */ 
void LOutput(char *a);   /* 大数输出 */
int StrLen(char *a); /* 求大数长度 */ 
int Compare(char *a,char *b);  /* a>=b 返回1,否则返回0 */
int Compare(char *a,char *b);  /* a>=b 返回1,否则返回0 */ 
void fun1(char *a,char *b,char *t);                /* 大数为正相加 */
void fun2(char *a,char *b,char *t);                 /* 大数为正相减 */
void LAdd(char *a,char *b,char *c);                  /* 大数相加 */ 
void LSub(char *a,char *b,char *c);              /* 大数相减 */
void LMul(char *a,char *b,char *c);              /* 大数相乘 */

int main()
{
	char a[Length],b[Length],c[Length];   /* 字符串数组存储大数 */
	LInput(a); 
	LInput(b);
//	LAdd(a,b,c);                 
//	LSub(a,b,c);              /* 大数相减 */
	LMul(a,b,c);              /* 大数相乘 */
    LOutput(c);
//	LDiv(a,b);              /* 大数相除 */ 
	return 0;
}

void LInput(char *a)   /* 大数输入,最高位前面的初始化为'0' */ 
{
	int i,j;
	char t;
	for(i=0;i<Length;i++)
	{
		scanf("%c",&a[i]);
		if(a[i]=='\n' || a[i]==' ')
		{
			j=i-1;     /* 记住输入字符长度 */ 
			while(i<Length)	a[i++]='0';  /* 补零 */ 
			break;
		}
	}
	if(i==Length) a[i-1]='\0';   /* 字符串最后一位'\0' */ 
	/* 逆序,高位存储在高字节 */ 
	for(i=0;i<=j;i++,j--)
	{
		t=a[i];
		a[i]=a[j];
		a[j]=t; 
	}	 
}

void LOutput(char *a)   /* 大数输出 */ 
{
	int j=StrLen(a)-1;
	if(a[0]=='\0')	printf("溢出\n");
	if(j==-1)    printf("%d",a[j]);   /* 0 的情况 */ 
	else
	for(;j>=0;j--)
		printf("%c",a[j]);
}

int StrLen(char *a)  /* 求大数长度,包括正负号 */ 
{
	int i;
	while(*a)	a++;   /* 从后序开始查找 */ 
	for(i=0;;i++)
		if(*--a !='0')	break;
	return Length-i-1;	
}
int Compare(char *a,char *b)  /* a>b 返回1,否则返回0 */ 
{
	int L1=StrLen(a)-1,L2=StrLen(b)-1;
	char a1[Length],a2[Length],i;
	/* a>=0,b<0 */ 
	if(a[L1]!='-' && b[L2]=='-')	
		return 1;
	/* a<0,b>=0 */ 
	if(a[L1]=='-' && b[L2]!='-')	return 0;
	/* a<0,b<0 */ 
	for(i=0;i<Length;i++)  /* 先存储,再使用,防止a,b的值被改变 */ 
	{
		a1[i] = a[i];
		a2[i] = b[i];
	}
	if((a[L1] == '-') && (b[L2] == '-'))
	{
		a1[L1]=a2[L2]='0';
		if(PCompare(a1,a2)) return 0;
		else return 1;
	}
	/* a>=0,b>=0 */
	return PCompare(a1,a2);  
}

int PCompare(char *a,char *b)  /* a,b均大于0,a>b 返回1,否则返回0 */ 
{
	int l1=StrLen(a)-1,l2=StrLen(b)-1;
	if(l1>l2)
		return 1;
	if(l1<l2)
		return 0;
	for(;l1>=0;l1--)
	{
//		printf("a[%d]=%c,b[%d]=%c\n",l1,a[l1],l1,b[l1]);	
		if(a[l1]>b[l1])	return 1;
		if(a[l1]<b[l1]) return 0; 
	}
	return 0;
}
void LAdd(char *a,char *b,char *c)                  /* 大数相加 */
{
	int L1=StrLen(a)-1,L2=StrLen(b)-1,l;
	/* a>0,b>0,a+b */
	if(a[L1]!='-' && b[L2]!='-')	   
		fun1(a,b,c);            
	/* a>0,b<0,转化成a-|b| */              
	if(a[L1]!='-' && b[L2]=='-')             
	{
		b[L2]='0';
		if(Compare(a,b))                      /* 若a>=|b|,则a-|b|,否则-(|b|-a) */ 
			fun2(a,b,c);    
		else
		{
			fun2(b,a,c);
			c[StrLen(c)]='-';
		}                         
	}
	/* a<0,b>0,转化成b-|a| */
	if(a[L1]=='-' && b[L2]!='-')		
	{
		a[L1]='0';
		if(Compare(b,a))                      /* 若b>=|a|,则b-|a|,否则-(|a|-b) */ 
			fun2(b,a,c);    
		else
		{
			fun2(a,b,c);
			c[StrLen(c)]='-';
		}                 
	}	
	/* a<0,b<0,转化成-(|b|+|a|) */
	if(a[L1]=='-' && b[L2]=='-')   
	{
		a[L1]='0';
		b[L2]='0';
		fun1(a,b,c);                     
		l=StrLen(c);
		c[l]='-';
	}
}

void fun1(char *a,char *b,char *t)                  /* 大数为正相加 */
{
	int i,c=0,s;        /* c进位 */ 	
	for(i=0;i<Length;i++)
	{
		s = a[i]-'0'+b[i]-'0';  
		if(s<10)           
		{
			t[i]=s+'0'+c;
			c=0;
		}
		else
		{
			t[i]=s-10+'0'+c;
			c=1;
		}			
	}
	if(c == 1)  /* 最高位进位,溢出 */ 
		t[0] = '\0';
	else       
		t[i-1] = '\0';
}

void fun2(char *a,char *b,char *t)                  /* 大数为正相减,且a>b */
{
	int i,c=0,s;        /* c借位 */ 
	for(i=0;i<Length;i++)   
	{
		s = a[i]-'0'-(b[i]-'0'); 
		if(s>=0)           
		{
			t[i]=s+'0'-c;
			c=0;
		}
		else
		{
			t[i]=s+10+'0'-c;
			c=1;
		}			
	}
	if(c == 1)  /* 最高位借位,溢出 */ 
		t[0] = '\0';
	else
		t[i-1] = '\0';
}

void LSub(char *a,char *b,char *c)              /* 大数相减 */
{
	int L1=StrLen(a)-1,L2=StrLen(b)-1,l;
	/* a>0,b>0,a-b */
	if(a[L1]!='-' && b[L2]!='-')	   
		if(Compare(a,b))                      /* 若a>=b,a-b,否则-(b-a)*/ 
			fun2(a,b,c);    
		else
		{
			fun2(b,a,c);
			c[StrLen(c)]='-';
		}   
	/* a>0,b<0,转化成a+|b| */	                          
	if(a[L1]!='-' && b[L2]=='-')              
	{
		b[L2]='0';
		fun1(a,b,c);                     
	}
	/* a<0,b>0,转化成-(b+|a|) */
	if(a[L1]=='-' && b[L2]!='-')		
	{
		a[L1]='0';
		fun1(a,b,c);                     
		l=StrLen(c);
		c[l]='-';        
	}	
	/* a<0,b<0,转化成|b|-|a| */
	if(a[L1]=='-' && b[L2]=='-')   
	{
		a[L1]='0';
		b[L2]='0';
		if(Compare(b,a))                      /* 若|b|>=|a|,则|b|-|a|,否则-(|a|-|b|) */ 
			fun2(b,a,c);    	
		else
		{
			fun2(a,b,c);
			c[StrLen(c)]='-';
		}   
	}
}
void fun3(char *a,char *b,char *c)              /* 大数为正数相乘 */
{
	int i,j,k,ct=0,s;        /* ct进位 */
	char t[Length];
	char *a1,*a2; 
	if(Compare(a,b)) {  /* 使a*b满足a>b */ 
		a1=a;
		a2=b;
	}
	else{
		a1=b;
		a2=a;
	}
	for(i=0;i<Length;i++)  /* 字符串初始化 */ 
		c[i]=t[i]='0';
	c[i-1]=t[i-1]='\0'; 
	for(i=0;i<StrLen(a2);i++)
	{
		for(k=0;k<i;k++)  /* 前i个字符初始化为'0' */ 
			t[k]='0';
		for(j=0;j<StrLen(a1);j++)
		{
			s = (a2[i]-'0')*(a1[j]-'0')+ct;   /* 乘法公式 */	 
			t[k+j]=s%10+'0';
			ct=s/10;      /* 进位 */
		}
		t[k+j]=ct+'0';
		fun1(t,c,c);   /* c+=k */ 
	}
	if(StrLen(a)+StrLen(b)>Length-1)	c[0]='\0';  /* 溢出 */	
}
void LMul(char *a,char *b,char *c)              /* 大数相乘 */
{
	int L1=StrLen(a)-1,L2=StrLen(b)-1,l;
	/* a>0,b>0,a*b */
	if(a[L1]!='-' && b[L2]!='-')	   
		fun3(a,b,c);                
	/* a>0,b<0,转化成-a*|b| */	                          
	if(a[L1]!='-' && b[L2]=='-')              
	{
		b[L2]='0';
		fun3(a,b,c);
		l=StrLen(c);
		c[l]='-';                    
	}
	/* a<0,b>0,转化成-|a|*b */
	if(a[L1]=='-' && b[L2]!='-')		
	{
		a[L1]='0';
		fun3(a,b,c);                     
		l=StrLen(c);
		c[l]='-';        
	}	
	/* a<0,b<0,转化成|b|*|a| */
	if(a[L1]=='-' && b[L2]=='-')   
	{
		a[L1]='0';
		b[L2]='0';
		fun3(a,b,c);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值