⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 numberoperate.cpp

📁 大数运算,效率非常高,很有收藏价值,值得你下载!
💻 CPP
字号:
// NumberOperate.cpp: implementation of the CNumberOperate class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "NumberOperate.h"

//*********************************************************************
//本类可实现位操作(与、或、非、异或、(循环)左移位、(循环)右移位),四则运算(均不限制位数)
//考虑到系统资源问题,请不要输入过大的数
//提供三个四则运算重载函数,用于不同场合及对速度不同要求时使用
//但要求速度的同时,对输入参数的合法性要求也不同,速度最慢,合法性要求最低
//相应,速度最快的函数,对参数的合法性要求最高
//在进行数的位操作时,结果返回的为二进制(最前面的零会自动去除),进行四则运算时,结果返回的为十进制
//作者:裴泽良
//时间:20051215
//********************************************************************

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CNumberOperate::CNumberOperate()
{

}

CNumberOperate::~CNumberOperate()
{

}

CString CNumberOperate::NumberAdd(CString number1, CString number2)
{	//完成两个数number1,number2的加法运算的整理工作,结果以CString型返回,此函数不对数据在十进制内是否合法作检测
	//仅接受十进制的数number1,number2
	if(number1=="" || number2=="")
		return "";
	while(number1!="" && number1.GetAt(0)=='0')
		number1.Delete(0,1);
	while(number2!="" && number2.GetAt(0)=='0')
		number2.Delete(0,1);
	if(number1=="")
		number1="0";
	if(number2=="")
		number2="0";
	int i=number1.GetLength(),j=number2.GetLength();
	int n=max(i,j);	//m为本次两个数相加后的进位,c为相加结果
	CString s="";	//s为结果
	char*buffers=s.GetBufferSetLength(n+1);//(任何两个数相加,其结果数字的数目必<=(两数字中大者的数目+1))
	n=Add(number1.GetBuffer(i),number2.GetBuffer(j),buffers);
	if(n!=-1)	//将n位之前的位去掉
		s.Delete(0,n+1);
	return s;
}

CString CNumberOperate::NumberSub(CString number1, CString number2)
{	//完成两个数number1,number2的减法运算的整理工作,结果以CString型返回,此函数不对数据在十进制内是否合法作检测
	//仅接受十进制的数number1,number2
	if(number1=="" || number2=="")
		return "";
	while(number1!="" && number1.GetAt(0)=='0')
		number1.Delete(0,1);
	while(number2!="" && number2.GetAt(0)=='0')
		number2.Delete(0,1);
	if(number1=="")
		number1="0";
	if(number2=="")
		number2="0";
	int i=number1.GetLength(),j=number2.GetLength(),m=0,c=0;	//m为本次两个数相减后的进位,c为相减结果

	int b=0;	//表number1大于number2,为1表number1小于number2
	if(i<j)
	{	//将number1与number2互换,使得number1大于number2
		int temp=i;
		i=j,j=temp;
		CString numbertemp=number1;
		number1=number2,number2=numbertemp;
		b=1;
	}
	else if(i==j)
	{
		for(int a=0;a<i;a++)
		{
			if(number1.GetAt(a)!=number2.GetAt(a))
			{
				if(number1.GetAt(a)<number2.GetAt(a))
				{
					CString numbertemp=number1;
					number1=number2,number2=numbertemp;
					b=1;
				}
				break;
			}
		}
	}
	CString s="";
	char*buffer1=number1.GetBuffer(i),*buffer2=number2.GetBuffer(j);
	char*buffers=s.GetBufferSetLength(i);
	int n=Sub(buffer1,buffer2,buffers);
	if(n!=-1)	//将n位之前的位去掉
		s.Delete(0,n+1);
	while(s!="" && s.GetAt(0)=='0')
		s.Delete(0,1);
	if(b==1)
		s="-"+s;
	if(s=="")
		s="0";
	return s;
}

CString CNumberOperate::NumberMulti(CString number1, CString number2)
{	//对number1,number2两个数进行相乘,结果以CString型返回(当两操作数达万位以上时,效率便不很理想)
	//此函数不对数据在十进制内是否合法作检测,且仅接受十进制的数number1,number2
	if(number1=="" || number2=="")
		return "";
	while(number1!="" && number1.GetAt(0)=='0')
		number1.Delete(0,1);
	while(number2!="" && number2.GetAt(0)=='0')
		number2.Delete(0,1);
	if(number1=="" || number2=="")
		return "0";
	CString s;
	int i=number1.GetLength(),j=number2.GetLength();
	char*buffers=s.GetBufferSetLength(i+j);	//存放结果(任何两个数相乘,其结果数字的数目必<=两相乘数数字数目之和)
	int n=Multi(number1.GetBuffer(i),number2.GetBuffer(j),buffers);
	if(n>1)	//将n位之前的位去掉
		s.Delete(0,n-1);
	while(s!="" && s.GetAt(0)=='0')
		s.Delete(0,1);	//去掉最前面的零
	return s;
}

BOOL CNumberOperate::NumberDiv(CString number1, CString number2, CString &resultint,CString &resultelse)
{	//结果形式为整数部分(resultint)+余数部分(resultelse),如果错误,返回FALSE,正常(但不一定正确,例:输入abcd)时返回TRUE
	//此函数不对数据在十进制内是否合法作检测,且仅接受十进制的数number1,number2
	resultint="";
	resultelse="";
	while(number1!="" && number1.GetAt(0)=='0')
		number1.Delete(0,1);	//被除数去前零
	while(number2!="" && number2.GetAt(0)=='0')
		number2.Delete(0,1);	//除数去前零
	if(number2=="")
		return FALSE;	//除数为零,错误
	if(number1=="")
	{	//被除数为零,直接返回零
		resultint="0";
		return TRUE;
	}
	int i=number1.GetLength(),j=number2.GetLength();
	char*buffer1=number1.GetBuffer(i),*buffer2=number2.GetBuffer(j);

	if(i<j)
	{	//结果无整数部分,仅小数
		resultint="0";
		resultelse=number1;
		return TRUE;
	}
	else if(i==j)
	{
		for(int a=0;a<i;a++)
		{
			if(buffer1[a]!=buffer2[a])
			{
				if(buffer1[a]<buffer2[a])
				{	//结果无整数部分,仅小数
					resultint="0";
					resultelse=number1;
					return TRUE;
				}
				break;
			}
		}
	}
	int intcount=0;
	char*buffers=resultint.GetBufferSetLength(i-j+1);	//结果数据(任何两个数相除,其结果数字的长度必<=(被除数及除数长度之差+1))
	resultelse=Div(buffer1,buffer2,buffers,intcount);
	resultint.Delete(intcount,i-j+1-intcount);
	while(resultint!="" && resultint.GetAt(0)=='0')
		resultint.Delete(0,1);
	while(resultelse!="" && resultelse.GetAt(0)=='0')
		resultelse.Delete(0,1);
	return TRUE;
}

int CNumberOperate::Add(char*buffer1, char*buffer2, char*buffers)
{	//对buffer1与buffer2中的数进行相加,结果放入buffers中,buffers的长度至少为max(buffer1,buffer2)+1
	//此函数不对数据或缓冲区空间是否足够作任何检测,旨在提高效率,速度
	int length1=strlen(buffer1),length2=strlen(buffer2);
	int m=0,c=0,n=max(length1,length2);	//m为本次两个数相加后的进位,c为相加结果
	while(length1>0 || length2>0)
	{
		if(length1==0)	//第一个数已取完
		{
			c=buffer2[length2-1]-0x30+m;
			length2--;
		}
		else
		{
			if(length2==0)	//第二个数已取完
			{
				c=buffer1[length1-1]-0x30+m;
				length1--;
			}
			else	//两个数均未取完
			{
				c=buffer1[length1-1]+buffer2[length2-1]-0x30-0x30+m;
				length1--,length2--;
			}
		}
		buffers[n]=c%10+0x30;
		n--;
		m=c/10;
	}
	if(m==1)
	{	//最后一次,最前一位相加,有进位
		buffers[n]='1';
		n--;
	}
	return n;
}

int CNumberOperate::Sub(char *buffer1, char *buffer2, char *buffers)
{	//对数buffer1与buffer2进行相减,但buffer1必须大于buffer2,且buffers的长度至少为buffer1-1;
	//此函数不对数据或缓冲区空间是否足够作任何检测,旨在提高效率,速度
	int i=strlen(buffer1),j=strlen(buffer2),m=0,c=0;	//m为本次两个数相减后的进位,c为相减结果
	int n=i-1;	//指示结果数据当前的位置
	while(i>0 || j>0)
	{
		if(j==0)	//第二个数已取完
		{
			c=buffer1[i-1]-0x30+m;
			i--;
		}
		else	//两个数均未取完
		{
			c=buffer1[i-1]-buffer2[j-1]+m;
			i--,j--;
		}
		if(c<0)
		{
			c+=10;
			m=-1;
		}
		else
			m=0;
		buffers[n]=c%10+0x30;
		n--;
	}
	return n;
}

int CNumberOperate::Multi(char*buffer1, char*buffer2, char*buffers)
{	//将buffer1,buffer2处的数据相乘,结果放在buffers中但从后至前,返回buffers最前面还有多少未用
	//buffers必须有buffer1+buffer2的长度再加1的空间
	//此函数不对数据或缓冲区空间是否足够作任何检测,旨在提高效率,速度
	int i=strlen(buffer1),j=strlen(buffer2),ii=i,m=0,n=i+j,nn=n+1,c=0,b=0;	//m为相乘时的进位,n为s的位置,nn为n的备份
	FillMemory(buffers,n,'0');		//初始化空间
	for(;j>0;j--,i=ii,m=0)
	{
		n=--nn;
		b=buffer2[j-1]-0x30;
		if(b==0)		//如果b的数等于零,则此趟不必计算
			continue;
		for(;i>0;i--,n--)
		{
			c=(buffer1[i-1]-0x30)*b+m;
			m=c/10+(c%10+buffers[n-1]-0x30)/10;	//求得本次的进位(为本次相乘的进位加上末位与已有结果相加的进位)
			buffers[n-1]=(c%10+buffers[n-1]-0x30)%10+0x30;	//保存结果
		}
		if(m!=0)	//如果进位不为零,则加入进位
			buffers[n-1]=m+0x30;
	}
	return n;
}

char* CNumberOperate::Div(char *buffer1, char *buffer2, char *bufferint, int &intcount)
{	//做buffer1除以buffer2操作(buffer1大于buffer2),结果整数放在bufferint中,返回余数,bufferint的长度至少为buffer1-buffer2+1
	//此函数不对数据合法性或数据或缓冲区空间是否足够作任何检测,旨在提高效率,速度
	intcount=0;		//intcount为整数部分的数量
	int i=strlen(buffer1),j=strlen(buffer2),a[2],b[4],temp[3];//a[0]:buffer1下一数据的位置,b[0]:除数的特征数据,b[1]:特征数据长度
	if(i<j)							//b[2]:指向上次运算数中参加运算时最后一位,即与被除数应该对齐时的位置
		return buffer1;				//b[3]:总是指向当前运算数中参加运算最后一位
	char*bufferss=NULL,*buffersconfirm=NULL,*buffertemp=NULL,*bufferb;

	b[1]=(j>4?4:j);	//提取除数的特征数据(前四位)
	bufferb=new char[b[1]+1];	//bufferb:除数的特征数据(<=4位)字符串形式
	bufferb[b[1]]='\0';
	CopyMemory(bufferb,buffer2,b[1]);
	b[0]=atoi(bufferb);	//除数的特征数据(<=4位) 数形式
	delete bufferb;

	bufferss=new char[j+2];	//从被除数中提取的将要处理的数据
	bufferss[j+1]='\0';
	buffersconfirm=new char[j+2];	//从被除数中提取的数据与m[0]相乘后的数据
	buffersconfirm[j+1]='\0';
	buffertemp=new char[b[1]+2];	//从被除数中提取的数据
	buffertemp[b[1]+1]='\0';
	char m[2];
	m[1]='\0';		//被除数除以除数一次所得的结果
	a[0]=0,a[1]=j;//a[1]:下次应从被除数中从a[0]所取数据的数目
	b[2]=a[1]-1,b[3]=a[1]-1;

	FillMemory(bufferss,j+1,'0');
	FillMemory(buffersconfirm,j+1,'0');
	FillMemory(buffertemp,b[1]+1,'0');

	while((a[0]+a[1])<=i)
	{
		for(;(a[0]+a[1])<=i;)
		{
			temp[1]=b[3]-b[2];
			if(temp[1]>0)
			{	//两对齐指针不在同一位置,对结果进行补零
				FillMemory(bufferint,temp[1],'0');
				bufferint+=temp[1];
				intcount+=temp[1];
				b[2]=b[3];
			}
			bufferss[0]='0';
			bufferss[j]='\0';
			CopyMemory(bufferss,buffer1+a[0],a[1]);
			temp[0]=NumberCompare(bufferss,buffer2);
			if(temp[0]>0)
			{	//从被除数中提取的数据大于除数,此时应求得大多少倍,即结果
				//本程序采用取两个数的前四位(可提高一次命中率),相除,取此数为结果,多位数时再验证一次
				buffertemp[0]='0';
				buffertemp[b[1]]='\0';
				CopyMemory(buffertemp,bufferss,b[1]+a[1]-j);	//从被除数提取数据放入buffertemp处
				m[0]=atoi(buffertemp)/b[0]+0x30;		//求出一次相除结果,此次有可能不正确,所以需下一次再验证
				buffersconfirm[0]='0';
				buffersconfirm[j]='\0';
				Multi(buffer2,m,buffersconfirm);
				if(j>4)
				{	//在多位数时,有必要再验证一次(最多一次)
					temp[0]=NumberCompare(bufferss,buffersconfirm);
					if(temp[0]<0)
					{
						m[0]--;		//m[0]大了,至多减1后,m[0]值肯定成立(可由数学方法证出)
						Multi(buffer2,m,buffersconfirm);	//重新计算buffersconfirm值
					}
				}
				*bufferint++=m[0];
				intcount++;
				temp[1]=0,temp[2]=0;
				while(bufferss[temp[1]]=='0')
					temp[1]++;	//把bufferss最前面的0去掉(若有,则最可能为一位)
				while(buffersconfirm[temp[2]]=='0')
					temp[2]++;	//把buffersconfirm最前面的0去掉(若有,则最可能为一位)
				Sub(bufferss+temp[1],buffersconfirm+temp[2],buffer1+a[0]+temp[1]);	//将减得的结果回加到被除数中
				while(buffer1[a[0]]=='0' && a[0]<=i)
					a[0]++;		//若最前一位为零,表明已约去,则去除掉
				a[1]=j;
				b[2]++,b[3]=a[0]+a[1]-1;	//两对齐指针做相应变化	
				break;
			}
			else if(temp[0]<0)	//当被除数小于除数时,被除数多加一位,即可
			{
				if(a[1]==j)
					a[1]=j+1;
				else
					a[0]++;	//若多加一位还除不掉(表明a[0]位为零),则舍弃a[0]位,再取j+1位
				b[3]=a[0]+a[1]-1;
			}
			else
			{	//当被除数等于除数时
				*bufferint++='1';
				intcount++;
				FillMemory(buffer1+a[0],a[1],'0');	//被除数相应位置零
				a[0]+=a[1],a[1]=j;
				b[2]++,b[3]=a[0]+a[1]-1;
				break;
			}
		}
	}
	temp[1]=b[3]-b[2];
	if(temp[1]>0 && b[3]<=i)
	{	//两对齐指针不在同一位置且b[3]指针合法,对结果进行补零
		FillMemory(bufferint,temp[1],'0');
		bufferint+=temp[1];
		intcount+=temp[1];
		b[2]+=temp[1];
	}
	bufferss[j]='0';
	buffertemp[b[1]]='0';
	buffersconfirm[j]='0';
	delete bufferss;
	delete buffersconfirm;
	delete buffertemp;
	return buffer1+a[0];
}

int CNumberOperate::NumberCompare(CString number1, CString number2)
{	//比较两数大小,number1大于number2返回1,相等返回0,小于返回-1
	int length1=number1.GetLength(),length2=number2.GetLength();
	char*buffer1=number1.GetBuffer(length1),*buffer2=number2.GetBuffer(length2);
	return NumberCompare(buffer1,buffer2);
}

int CNumberOperate::NumberCompare(char*buffer1, char*buffer2)
{	//比较两数大小,number1大于number2返回1,相等返回0,小于返回-1
	while(buffer1[0]=='0')
		buffer1++;	//若buffer1开始处为零,buffer1指针右移
	while(buffer2[0]=='0')
		buffer2++;
	int i=strlen(buffer1),j=strlen(buffer2);//,m=0,n=0;
	if(i>j)
		return 1;
	else if(i<j)
		return -1;
	else if(i==j)
	{
		for(int a=0;a<i;a++)
		{
			if(buffer1[a]!=buffer2[a])
			{
				if(buffer1[a]<buffer2[a])
					return -1;
				else
					return 1;
				break;
			}
		}
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -