比较好的大整数四则运算

#include<iostream>
using namespace std;
   

#define INT_BIT_MAX 255  

#define FLOAT_BIT_MAX 255  
#ifndef CONST  

   #ifdef __cplusplus  

       #define CONST const  

   #else  

       #define CONST  

    #endif  

 #endif  

typedef struct tagWTNumber {
	int intbits;                     /* 整数数位*/
	int floatbits;                   /* 小数有效数位*/
	char infinite;                   /* 无穷大*/
	char sign;                       /* 符号*/
	char intpart[INT_BIT_MAX];       /* 整数部分*/
	char floatpart[FLOAT_BIT_MAX];   /* 小数部分*/
} WTNumber;
/* 算术函数指针类型.*/
typedef void (*PFNCALC)(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes);

/* 初始化WTNumber为0.*/
void InitWTNumberToZero(WTNumber *pNum);
/* 判断需要多少个字符空间存储WTNumber转换的字符串.*/
int CharArrLenByWTNumber(CONST WTNumber* pNum);
/* 从字符串转换到WTNumber.*/
void CharArrToWTNumber(CONST char *arr,WTNumber *pNum);
/* 从WTNumber转换到字符串.*/
void WTNumberToCharArr(char *szBuf,CONST WTNumber *pNum);
/* 调节数位,删除最高整数位是0的和最低小数位是0的数位.*/
void AdjustBits(WTNumber *pNum);
/* 移动小数点,deta=0不移动,deta<0往左移动,deta>0往右移动.*/
void MoveFloatPoint(WTNumber *pNum,int deta);
/* 使无穷大 */
void MakeInfinite(WTNumber *pNum);
/* 根据算术函数返回结果 */
char *Result(CONST char *val1,CONST char *val2,PFNCALC pfnCalc);
/* 比较2个数大小 */
int WTCompare(CONST WTNumber* pn1,CONST WTNumber* pn2);
/* 判断是否为0 */
int IsZero(CONST WTNumber *pNum);
/* 加法*/
void WTAdd(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes);
/* 乘法*/
void WTMultiply(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes);
/* 减法*/
void WTSubtract(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes);
/* 除法*/
void WTDivide(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes);
void InitWTNumberToZero(WTNumber *pNum)
{
	memset(pNum,0,sizeof(WTNumber));
}
void AdjustBits(WTNumber *pNum)
{
	while(pNum->intbits>1&&pNum->intpart[pNum->intbits-1]==0) pNum->intbits--;
	while(pNum->floatbits&&pNum->floatpart[pNum->floatbits-1]==0) pNum->floatbits--;
}
void MoveFloatPoint(WTNumber *pNum,int deta)
{
	/* deta<0则往左移动小数点,deta>0则向右移动小数点 */
	if(deta)
	{
		WTNumber n=*pNum;
		InitWTNumberToZero(pNum);
		pNum->sign=n.sign;
		if(deta<0)
		{
			int i;
			deta=-deta;
			for(i=deta;i<n.intbits;i++)
			{
				pNum->intpart[pNum->intbits++]=n.intpart[i];
			}
			for(i=deta-1;i>=0;i--)
			{
				pNum->floatpart[pNum->floatbits++]=n.intpart[i];
			}
			for(i=0;i<n.floatbits;i++)
			{
				pNum->floatpart[pNum->floatbits++]=n.floatpart[i];
			}
		}
		else
		{
			int i;
			for(i=deta;i<n.floatbits;i++)	/* 处理小数部分*/
			{
				pNum->floatpart[pNum->floatbits++]=n.floatpart[i];
			}
			for(i=deta-1;i>=0;i--)	/* 小数到整数的部分*/
			{
				pNum->intpart[pNum->intbits++]=n.floatpart[i];
			}
			for(i=0;i<n.intbits;i++)	/* 整数部分*/
			{
				pNum->intpart[pNum->intbits++]=n.intpart[i];
			}
		}
	}
	AdjustBits(pNum);
}

int CharArrLenByWTNumber(CONST WTNumber* pNum)
{
	int len = pNum->floatbits+pNum->intbits+1;
	if(pNum->intbits==0) len++;	/* .1 --> 0.1*/
	if(pNum->floatbits) len++;	/* '.'*/
	if(pNum->sign) len++;		/* '-'*/
	if(pNum->infinite) return 11;    /* #INFINITE */
	return len;
}
void CharArrToWTNumber(CONST char *arr,WTNumber *pNum)
{
	char *point;
	InitWTNumberToZero(pNum);
	if(*arr=='-')	/* 如果是负数*/
	{
		arr++;
		pNum->sign=1;
	}
	point=strchr(arr,'.');
	if(point)	/* 找到小数点 */
	{
		int n=pNum->intbits=point-arr;	/* 计算出整数数位 */
		while(n)	/* 整数数位不==0则循环 */
		{
			pNum->intpart[pNum->intbits-n]=arr[n-1]-'0';	/* 将数字低位存在低下标元素*/
			n--;
		}
		while(*++point)
		{
			pNum->floatpart[pNum->floatbits]=*point-'0';
			pNum->floatbits++;
		}
	}
	else	/* 说明没写小数点,全是整数.*/
	{
		int n=pNum->intbits=strlen(arr);
		while(n)
		{
			pNum->intpart[pNum->intbits-n]=arr[n-1]-'0';
			n--;
		}
	}
	AdjustBits(pNum);
	/* 处理-0 和0的情况*/
	if(pNum->floatbits==0)
	{
		if(pNum->intbits==0 || pNum->intbits==1&&pNum->intpart[0]==0)
			pNum->sign=0;
	}
}

void WTNumberToCharArr(char *szBuf,CONST WTNumber* pNum)
{
	int n=pNum->intbits,c;
	memset(szBuf,0,CharArrLenByWTNumber(pNum));
	if(pNum->sign)	/* 如果是负数*/
	{
		*szBuf++='-';
	}
	if(pNum->infinite)
	{
		strcat(szBuf,"#INFINITE");
		return;
	}
	while(n)
	{
		szBuf[pNum->intbits-n]=pNum->intpart[n-1]+'0';
		n--;
	}
	c=0;	/* 是否加了0*/
	if(pNum->intbits==0) {
		strcat(szBuf,"0");
		c=1;
	}
	if(pNum->floatbits) strcat(szBuf,".");
	n=0;
	while(n<pNum->floatbits)
	{
		szBuf[pNum->intbits+1+n+c]=pNum->floatpart[n]+'0';
		n++;
	}
}

char *Result(CONST char *val1,CONST char *val2,PFNCALC pfnCalc)
{
	static char *s_szRes=NULL;
	WTNumber n1,n2,res;
	if(s_szRes) {
		/*delete [] s_szRes;*/
		free(s_szRes);
		s_szRes=NULL;
	}
	CharArrToWTNumber(val1,&n1);
	CharArrToWTNumber(val2,&n2);
	pfnCalc(&n1,&n2,&res);
/*	s_szRes = new char[CharArrLenByWTNumber(&res)];*/
	s_szRes=(char*)malloc(CharArrLenByWTNumber(&res)*sizeof(char));
	WTNumberToCharArr(s_szRes,&res);
	return s_szRes;
}

int WTCompare(CONST WTNumber* pn1,CONST WTNumber* pn2)
{
	/* 首先是比较符号*/
	if(pn1->sign==0&&pn2->sign!=0)	/* pn1是正数,pn2是负数*/
		return 1;	/* >*/
	else if(pn1->sign!=0&&pn2->sign==0)	/* pn1是负数,pn2是正数*/
		return -1;	/* <*/
	else	/* 同号状态*/
	{
		/* 比较整数部分*/
		if(pn1->intbits>pn2->intbits)	/* pn1整数数位多*/
			return pn1->sign?-1:1;
		else if(pn1->intbits<pn2->intbits)
			return pn1->sign?1:-1;
		else	/* 整数数位相同*/
		{
			int i=pn1->intbits-1;	/*指到最高位*/
			while(i>=0)
			{
				if(pn1->intpart[i]>pn2->intpart[i])
					return pn1->sign?-1:1;
				else if(pn1->intpart[i]<pn2->intpart[i])
					return pn1->sign?1:-1;
				else i--;
			}
			/* 整数部分相同,比较小数部分*/
			for(i=0;i<pn1->floatbits&&i<pn2->floatbits;)
			{
				if(pn1->floatpart[i]>pn2->floatpart[i])
					return pn1->sign?-1:1;
				else if(pn1->floatpart[i]<pn2->floatpart[i])
					return pn1->sign?1:-1;
				else i++;
			}
			if(i<pn1->floatbits) return pn1->sign?-1:1;
			if(i<pn2->floatbits) return pn1->sign?1:-1;
			return 0;	/* 相等*/
		}
	}
}
void MakeInfinite(WTNumber *pNum)
{
	pNum->infinite=1;
}
int IsZero(CONST WTNumber* pNum)
{
	if(pNum->floatbits==0&&pNum->intbits==0) return 1;
	if(pNum->floatbits==0&&pNum->intbits==1&&pNum->intpart[0]==0) return 1;
	return 0;
}

void WTAdd(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes)
{
	InitWTNumberToZero(pRes);
	if(pn1->sign^pn2->sign)	/*异号*/
	{
		WTNumber n2=*pn2;
		n2.sign=pn1->sign;
		WTSubtract(pn1,&n2,pRes);
	}
	else	/*同号*/
	{
		int maxfloatbits=pn1->floatbits>pn2->floatbits?pn1->floatbits:pn2->floatbits;
		int addbit=0;	/* 进位值*/
		int i,j;
		for(i=maxfloatbits-1;i>=0;i--)
		{
			int value=pn1->floatpart[i]+pn2->floatpart[i]+addbit;
			addbit=value/10;	/* 看看是否超过10. 设置进位值*/
			pRes->floatpart[i]=value%10;
		}
		pRes->floatbits=maxfloatbits;
		/* 到此,小数部分计算完毕.*/
		for(j=0;j<pn1->intbits||j<pn2->intbits;j++)
		{
			int value=pn1->intpart[j]+pn2->intpart[j]+addbit;
			addbit=value/10;
			pRes->intpart[j]=value%10;
			pRes->intbits++;
		}
		if(addbit>0)
		{
			pRes->intpart[j]=addbit;
			pRes->intbits++;
		}
		pRes->sign=pn1->sign;	/*决定符号*/
		AdjustBits(pRes);
	}
}

void WTMultiply(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes)
{
	WTNumber z1=*pn1,z2=*pn2;
	WTNumber sum={0};
	int i,j;
	InitWTNumberToZero(pRes);
	MoveFloatPoint(&z1,z1.floatbits);
	MoveFloatPoint(&z2,z2.floatbits);
	/* 计算z1*z2 */
	for(i=0;i<z2.intbits;i++)
	{
		WTNumber tmp={0};	/* 存放临时乘积*/
		int addbit=0;
		tmp.intbits=z1.intbits+i;
		for(j=0;j<z1.intbits;j++)
		{
			int value = z2.intpart[i]*z1.intpart[j]+addbit;
			addbit=value/10;
			tmp.intpart[j+i]=value%10;
		}
		if(addbit)
		{
			tmp.intpart[j+i]=addbit;
			tmp.intbits++;
		}
		WTAdd(&sum,&tmp,pRes);
		sum=*pRes;
	}
	*pRes=sum;
	MoveFloatPoint(pRes,-(pn1->floatbits+pn2->floatbits));
	/* 判断符号,异号为负*/
	if(pn1->sign^pn2->sign) pRes->sign=1;
}

void WTSubtract(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes)
{
	InitWTNumberToZero(pRes);
	if(pn1->sign^pn2->sign)	/* 异号情况*/
	{
		WTNumber n2=*pn2;
		n2.sign=pn1->sign;
		WTAdd(pn1,&n2,pRes);
	}
	else	/* 同号情况*/
	{
		int cmp=WTCompare(pn1,pn2);
		int swapflag,i,maxfloatbits,subtractbit;
		if(cmp==0) return;	/* 相等就没必要再减了.*/
		swapflag=pn1->sign==0?cmp==-1:cmp==1;
		if(swapflag)
		{
			CONST WTNumber* p=pn1;
			pn1=pn2;
			pn2=p;
		}
		maxfloatbits=pn1->floatbits>pn2->floatbits?pn1->floatbits:pn2->floatbits;
		subtractbit=0;	/* 退位值*/
		/* 先计算小数部分*/
		for(i=maxfloatbits-1;i>=0;i--)
		{
			if(pn1->floatpart[i]-subtractbit<pn2->floatpart[i])
			{
				int value=pn1->floatpart[i]-pn2->floatpart[i]-subtractbit+10;
				subtractbit=1;
				pRes->floatpart[i]=value;
			}
			else
			{
				int value=pn1->floatpart[i]-pn2->floatpart[i]-subtractbit;
				subtractbit=0;
				pRes->floatpart[i]=value;
			}
		}
		pRes->floatbits=maxfloatbits;
		/* 至此小数部分计算完毕.*/
		for(i=0;i<pn1->intbits||i<pn2->intbits;i++)
		{
			if(pn1->intpart[i]-subtractbit<pn2->intpart[i])
			{
				int value=pn1->intpart[i]-pn2->intpart[i]-subtractbit+10;
				subtractbit=1;
				pRes->intpart[i]=value;
			}
			else
			{
				int value=pn1->intpart[i]-pn2->intpart[i]-subtractbit;
				subtractbit=0;
				pRes->intpart[i]=value;
			}
			pRes->intbits++;
		}
		pRes->sign=swapflag?!pn1->sign:pn1->sign;	/*决定符号*/
		AdjustBits(pRes);
	}
}

void WTDivide(CONST WTNumber* pn1,CONST WTNumber* pn2,WTNumber* pRes)
{
	WTNumber z1=*pn1,z2=*pn2;
	int deta=z2.floatbits-z1.floatbits;
	MoveFloatPoint(&z1,z1.floatbits);
	MoveFloatPoint(&z2,z2.floatbits);
	InitWTNumberToZero(pRes);
	if(IsZero(pn1)) return ;
	if(IsZero(pn2)) {
		pRes->sign=pn1->sign;
		MakeInfinite(pRes);
		return ;
	}
	z1.sign=z2.sign=0;                /*统一符号,便于比较大小*/
	while(z1.intbits!=z2.intbits) {    /*确保数位相等,这步耗费很多时间*/
		if(z1.intbits<z2.intbits) {
			MoveFloatPoint(&z1,1);
			deta--;
		} else {
			MoveFloatPoint(&z2,1);
			deta++;
		}
	}
	while(pRes->floatbits<(INT_BIT_MAX/2)) {
		int cmp=WTCompare(&z1,&z2);
		int n=10;
		WTNumber mulres={0},subres={0};
		if(cmp==-1) {      /*z1<z2*/
			MoveFloatPoint(&z1,1);
			pRes->floatpart[pRes->floatbits++]=0;
			continue;
		} else if(cmp==0) { /*z1==z2*/
			pRes->floatpart[pRes->floatbits++]=1;
			break;
		}
		do {	/*找商*/
			WTNumber tmp={0};
			tmp.intpart[0]=--n;
			tmp.intbits=1;
			WTMultiply(&z2,&tmp,&mulres);
		} while((cmp=WTCompare(&mulres,&z1))==1);
		pRes->floatpart[pRes->floatbits++]=n;
		if(cmp==0) break;
		WTSubtract(&z1,&mulres,&subres);
		MoveFloatPoint(&subres,1);
		z1=subres;
	}
	MoveFloatPoint(pRes,1);
	MoveFloatPoint(pRes,deta);
	/* 判断符号,异号为负*/
	if(pn1->sign^pn2->sign) pRes->sign=1;
}
typedef char CHARARR[256];

int main()
{
	CHARARR num1;
	CHARARR num2;
	puts("Input two numbers,please:");
	while(scanf("%s%s",num1,num2)!=-1) {
		printf("The result of addition:\n%s\n",Result(num1,num2,WTAdd));
		printf("The result of subtration:\n%s\n",Result(num1,num2,WTSubtract));
		printf("The result of multiplication:\n%s\n",Result(num1,num2,WTMultiply));
		printf("The result of divide:\n%s\n",Result(num1,num2,WTDivide));
		puts("Input two numbers,please:");
	}
	return 0;
}
http://www.ilikec.com/?p=167

你可能感兴趣的:(比较好的大整数四则运算)