C语言-大整数四则运算

int的存储空间有限,利用"串"的结构,分享一则“大整数”简单四则运算。


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

typedef struct bigint
{
	char *num;                //指向长整数数组(序号0中保存着最高位) 
	char minus;               //符号(1表示正数,-1表示负数) 
	int digit;                 //保存该数的位数(实际位数) 
}BIGINT, *pBIGINT; 

void BigIntTrans(pBIGINT num1)    //将字符串转为数字表示 
{
	char *temp;                   //临时数组 
	int i,k,len;
	len=strlen(num1->num);       //字符串长度 
	
	//分配内存
	if(!(temp = (char *)malloc(sizeof(char)* len)))        
	{
		printf("内存分配失败!\n");
		exit(0);
	} 
	i=0;
	num1->minus=1;                 //保存为正数 
	if(num1->num[0]=='-')          //判断是否为负数 
	{
		num1->minus=-1;
		i++;
	}
	k=0;                            //数字位数计数器 
	while(num1->num[i]!='\0')       //字符串未结束 
	{
		if(num1->num[i]>='0' && num1->num[i] <='9')     //数字为0~9 
			//将ASCII码转换为对应数字 
			temp[k]=num1->num[i]-'0';                  
			k++; 
		} 
		i++;
	}     
	
	for(i=0;i<num1->digit;i++)     //清空数组各元素 
		num1->num[i]=0;
	num1->digit=k;                     //转换后的数据位数 
	for(i=0,k--;k>=0;k--,i++)          //将临时数组各位置反置保存到数组num中 
		num1->num[i]=temp[k];
	BigIntTrim(num1);                   //整理输入的大整数 
}

void BigIntTrim(pBIGINT num1)           //整理大整数,去掉前面多余的0 
{
	int i;
	for(i=num1->digit-1;i>=0;i--)      //从高位检查是否为0 
	{
		if(num1->num[i] !=0)             //遇到不为0的最高位 
		break;                     //跳出循环 
	}
	if(i<0)                         //若余数全部为0 
	{
		num1->digit=1;                     //设置余数位数为1 
		num1->num[0]=0;
	}else
	num1->digit=i+1;                 //余数位数 
} 

void BigIntPrint(pBIGINT result)      //输出大整数 
{
	int j;
	if(result->minus ==-1)           //是负数 
		printf("-");                 //输出负数 
		 //若大整数为0 
		if(result->digit ==1 &&result->num[0]==0)     
			printf("0");
		else                         //不为0 
		{
			//从高位到低位输出 
			for(j=result->digit-1;j>=0;j--)             
				printf("%d",result->num[j]);
		} 
} 

int BigIntEqual(pBIGINT num1,pBIGINT num2)         //比较绝对值大小 
{
	int i;
	//num1的位数大于num2 
	if(num1->digit>num2->digit)               
		return 1;
	//num1的位数小于num2 
	else if(num1->digit<num2->digit)           
		return -1;
		else                                 //两数位数相等 
		{
			i=num1->digit-1;                  //num1的数据位数 
			while(i>=0)                       //从高位向地位比 
			{
				//num1对应位大于num2 
				if(num1->num[i]>num2->num[i])        
					return 1;
				//num1对应位小于num2
				else if(num1->num[i]<num2->num[i])       
					return -1;
				else                            //比较下一位 
					i--;
			}
		}
		return 0;                               //相等 
} 

void BigIntAdd(pBIGINT num1,pBIGINT num2,pBIGINT result)
{
	int i;
	i=BigIntEqual(num1,num2);            //比较两数绝对值大小 
	if(i<0)                              //num1绝对值小于num2 
	{
		pBIGINT temp;
		temp=num1;                      //交换两数 
		num1=num2;
		num2=temp;
	}
	if(num1->minus * num2->minus <0)         //符号不同,则执减法 
	{
		if(i==0)                              //两数相等 
		{
			//结果长度为一位数,就是数值0 
			result->digit =1;                 
			result->num[0]=0;                 //结果值为0 
			result->minus =1;                 //结果设为正号 
			return;                            //返回 
		}
		//调用相减函数完成异号相加 
		BigIntSub1(num1,num2,result);           
	}else
	//调用相加函数完成同号相加 
	BigIntAdd1(num1,num2,result);               
} 

void BigIntAdd1(pBIGINT num1,pBIGINT num2,pBIGINT result)
{
	int i,carry;
	carry=0;                              //清除进位 
	result->minus =num1->minus;           //保存符号 
	//将被加数复制到结果数组中 
	for(i=0;i<num1->digit;i++)             
		result->num[i]=num1->num[i];
	//num2中的数小,可能位数也少些 
	for(i=0;i<num2->digit;i++)               
	{
		//将对应位的数和进位数相加 
		result->num[i]=result->num[i]+num2->num[i]+carry;    
		carry=result->num[i]/10;       //计算进位数据 
		result->num[i]=result->num[i]%10;     //保留一位 
	}
	if(carry)                       //若最后还有进位 
		result->num[i]=result->num[i]+carry;
	BigIntTrim(result);                //整理结果 
} 

//减法函数
void BigIntSub(pBIGINT num1,pBIGINT num2,pBIGINT result)      
{
	num2->minus =-1 * num2 ->minus;       //将减数的符号取反 
	BigIntAdd(num1,num2,result);          //调用加法函数 
} 

//异号相减函数 
void BigIntSub1(pBIGINT num1,pBIGINT num2,pBIGINT result)     
{
	int i,borrow;
	result->minus =num1->minus;         //结果符号 
	borrow=0;
	//将被减数的内容复制到结果中 
	for(i=0;i<num1->digit;i++)                
		result->num[i]=num1->num[i];
	for(i=0;i<=num2->digit;i++)
	{
		//num1减去num2,并减去低位的借位 
		result->num[i]=result->num[i]-num2->num[i]-borrow;		                                     
		if(result ->num[i]<0)             //若为负数 
		{
			result->num[i]=10+result->num[i];    //向高位借位 
			borrow=1;                   //设置借位数 
		}else
			borrow=0;
	}
	if(borrow==1)
		result->num[i]=result->num[i]-borrow;
	i=num1->digit;
	while(i>0)
	{
		if(result->num[i]==0)
			i--;
		else
			break;
	} 
	result->digit=i+1;               //保存结果位数 
	BigIntTrim(result);              //整理结果 
} 



void BigIntMul(pBIGINT num1,pBIGINT num2,pBIGINT result)
{
	char carry,temp;
	int i,j,pos;
	//结果数组和中间数清0 
	for(i=0;i<num1->digit+num2->digit;i++)     
		result->num[i]=0;
	//用乘数的每一位乘以被乘数 
	for(i=0;i<num2->digit;i++)               
	{
		carry=0;                              //清除进位 
		//被乘数的每一位 
		for(j=0;j<num1->digit;j++)                  
		{
			//相乘并加上进位 
			temp=num2->num[i] * num1->num[j]+carry;    
			 //计算进位carry 
			carry =temp/10; 
			//计算当前位的值                       
			temp=temp%10;                         
			pos=i+j;
			//计算结果累加到临时数组中 
			result->num[pos]+=temp;             
			carry=carry+result->num[pos]/10;           //计算进位 
			result->num[pos]=result->num[pos]%10; 
		}
		if(carry>0)
		{
			result->num[i+j]=carry;                //加上最高位进位 
			result->digit=i+j+1;                  //保存结果位数 
		}else
			result->digit=i+j;                   //保存结果位数 
	} 
	result->minus=num1->minus * num2->minus;        //结果的符号 
} 


void BigIntDiv(pBIGINT num1,pBIGINT num2,pBIGINT result,pBIGINT residue)
                                                      //除法函数 
{
	BIGINT quo1,residol,quo2;
	int i,j,k,m;               //k保存试商结果,m保存商的位数 
	char t;
	result->minus = num1->minus * num2->minus;        //商的符号 
	 //分配余数的内存空间
	residue->num =(char *)malloc(sizeof(char) * num2->digit);   
	for(i=0;i<residue->digit;i++)            //将余数全部清0 
		residue->num[i]=0;
	m=0;
	for(i=num1->digit-1;i>=0;i--)
	{
		//重新设置余数的位数比除数多一位 
		residue->digit=num2->digit+1;       
		for(j=num2->digit-1;j>0;j--)               //移余数 
			residue->num[j]=residue->num[j-1];
		//复制被除数中的一位到余数的最低位中 
		residue->num[0]=num1->num[i];          
		BigIntTrim(residue);                  //整理余数 
		k=0;                                      //试商 
		 //比较余数与除数的大小 
		while(BigIntEqual(residue,num2)>=0)    
		{
			BigIntSub1(residue,num2,residue);     //用余数减去除数,差值保存在余数中 
			k++;                       //试商加1 
		} 
		result->num[m++]=k;           //保存商 
	}
	result->digit=m;                 //保存商的位数 
	for(i=0;i<m/2;i++)              //反转商的值            
	{
		t=result->num[i];
		result->num[i]=result->num[m-1-i];
		result->num[m-1-i]=t; 
	} 
	BigIntTrim(result);          //整理商 
	BigIntTrim(residue);            //整理余数 
 }
 
 int main()
 {
	 //参与运算的数,结果,余数 
 	BIGINT num1,num2,result,residue;              
	 int i=0,len;
	 char op;
	 printf("输入最大数的位数:");
	 scanf("%d",&len);
	 if(!(num1.num=(char *)malloc(sizeof(char) * (len+1))) )
	 {
	 	printf("内存分配失败!\n");
	 	exit(0);
	 }
	 num1.digit=len +1;
	 if(!(num2.num=(char *)malloc(sizeof(char) * (len +1))))
	 {
	 	printf("内存分配失败!\n");
	 	exit(0);
	 }
	 num2.digit=len+1;
	 if(!(result.num=(char *)malloc(sizeof(char) * (2*len +1))))
	 {
	 	printf("内存分配失败!\n");
	 	exit(0);
	 }
	 result.digit=2*len+1;
	 for(i=0;i<result.digit;i++)             //清空结果集 
	 	result.num[i]=0;
	printf("选择大整数的运算(+,-,*,/):");
	fflush(stdin);
	scanf("%c",&op);
	switch(op)
	{
		case '+':
			printf("\n输入被加数:");
			scanf("%s",num1.num); 
			printf("\n输入加数:");
			scanf("%s",num2.num); 
			BigIntTrans(&num1);
			BigIntTrans(&num2);
			BigIntAdd(&num1,&num2,&result);     //加法 
			break;
		case '-':
			 printf("\n输入被减数:");
			scanf("%s",num1.num); 
			printf("\n输入减数:");
			scanf("%s",num2.num); 
			BigIntTrans(&num1);
			BigIntTrans(&num2);
			BigIntSub(&num1,&num2,&result);      //减法 
			break;
		case '*':
			printf("\n输入被乘数:");
			scanf("%s",num1.num); 
			printf("\n输入乘数:");
			scanf("%s",num2.num); 
			BigIntTrans(&num1);
			BigIntTrans(&num2);
			BigIntMul(&num1,&num2,&result);      //乘法 
			break; 
		case '/':
		printf("\n输入被除数:");
			scanf("%s",num1.num); 
			printf("\n输入除数:");
			scanf("%s",num2.num); 
			BigIntTrans(&num1);
			BigIntTrans(&num2);
			if(num2.digit==1 && num2.num[0]==0)        //大整数为0 
				printf("除数不能为0!\n");
			else
				BigIntDiv(&num1,&num2,&result,&residue);    //除法 
			break; 
	}
	if(op=='/')
	{
		//为除法且除数不为0 
		if(!(num2.digit==1 && num2.num[0]==0))        
		{
			printf("商:");
			BigIntPrint(&result);
			 printf("\t余数:");
			 BigIntPrint(&residue);
		}
	}else
	{
		printf("结果:");
		BigIntPrint(&result); 
	}
	getch();
	return 0;
 }

资源下载位置:

http://pan.baidu.com/s/1sl1icmp
http://download.csdn.net/download/u013553804/9493994


更新于2019-06-18
在这里插入图片描述
在这里插入图片描述

  • 12
    点赞
  • 100
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值