大数计算 c++实现

为实现一个不会溢出的四则运算计算器,我们需要将数据存入字符串中,并自己实现加减乘除的逻辑。

存储结构设计:

为了方便计算,将符号位,整数部分,小数部分分别存储

enum SIGN
{
	POSITIVE,
	NEGATIVE
};

class Num
{
protected:
	SIGN _sign;        //符号位
	string _int;       //整数位
	string _float;     //小数位
public:
	Num()
		:_sign(POSITIVE)
	{}
}

分别重载常见运算符,并定义拷贝构造函数

	bool operator>(Num& a)
	{
		if(IsZero(*this)&&IsZero(a))
			return false;
		if(_sign==NEGATIVE&&a._sign==POSITIVE)
			return false;
		else if(_sign==POSITIVE&&a._sign==NEGATIVE)
			return true;

		if(_sign==POSITIVE&&a._sign==POSITIVE)
		{
			if(_int.length()>a._int.length())
				return true;
			else if(_int.length()0)
					return true;
				else if(strcmp(_int.c_str(),a._int.c_str())==0)
				{
				string::iterator it1=_float.begin();
				string::iterator it2=a._float.begin();

				while(it1!=_float.end()&&it2!=a._float.end())
				{
					if(*it1<*it2)
						return false;
					it1++;
					it2++;
				}
				while(it2!=a._float.end())
				{
					return false;
				}
				while(it1!=_float.end())
				{
					return true;
				}
				}
				return false;
			}
		}

		if(_sign==NEGATIVE&&a._sign==NEGATIVE)
		{
			if(_int.length()>a._int.length())
				return false;
			else if(_int.length()0)
					return false;
				else if(strcmp(_int.c_str(),a._int.c_str())==0)
				{
				string::iterator it1=_float.begin();
				string::iterator it2=a._float.begin();

				while(it1!=_float.end()&&it2!=a._float.end())
				{
					if(*it1<*it2)
						return true;
					else if(*it1>*it2)
						return false;
					it1++;
					it2++;
				}
				while(it1!=_float.end())
				{
					return false;
				}
				while(it2!=a._float.end())
					return true;
				}
				return false;
			}
		}
		return true;
	}

	bool operator==(Num& a)
	{
		if(IsZero(*this)&&IsZero(a))
			return true;
		if(_sign==NEGATIVE&&a._sign==POSITIVE)
			return false;
		else if(_sign==POSITIVE&&a._sign==NEGATIVE)
			return false;

		if(_int.length()!=a._int.length()||_float.length()!=a._float.length())
			return false;
		else if(_int.length()==a._int.length()&&strcmp((_int.c_str()),a._int.c_str())!=0)
			return false;
		else if(_float.length()==a._float.length()&&strcmp((_float.c_str()),a._float.c_str())!=0)
			return false;

		return true;
	}

	bool operator<(Num& a)
	{
	return !(*this>a||*this==a);
	}

	bool operator>=(Num& a)
	{
	return *this>a||*this==a;
	}

	bool operator<=(Num& a)
	{
	return *this
	Num(Num& a)
	{
		_sign=a._sign;
		_int=a._int;
		_float=a._float;
	}

实现加法部分的逻辑

思路:

1.区别同号,异号相加

2.同号相加:从小数部分开始,不对齐的部分直接赋给结果,对位的部分按照加法规则相加,整数部分,对位部分相加,不对位部分加上进位赋值给结果

3.异号相加:按照减法计算,其余逻辑与2相似

	Num add(Num& a,Num& b)
	{
		Num ret;
		int flag=0;//进位符
		if(a.IsZero())
			return b;
		if(b.IsZero())
			return a;
		if(a._sign==b._sign)//同号相加
		{
			ret._sign=a._sign;
			int len1=a._float.length();
			int len2=b._float.length();
			string::reverse_iterator rt1=a._float.rbegin();
			string::reverse_iterator rt2=b._float.rbegin();
			while(len1>len2)//小数部分
			{
				len1--;
				ret._float.insert(0,1,*rt1);
				rt1++;
			}
			while(len2>len1)
			{
				len2--;
				ret._float.insert(0,1,*rt2);
				rt2++;
			}
			while(len1==len2&&rt1!=a._float.rend()&&rt2!=b._float.rend())
			{
				int tmp=(*rt1-'0')+(*rt2-'0')+flag;
				flag=tmp/10;
				tmp=tmp%10;
				ret._float.insert(0,1,tmp+'0');
				rt2++;
				rt1++;
				len1--;
				len2--;
			}

			rt1=a._int.rbegin();
			rt2=b._int.rbegin();

			while(rt1!=a._int.rend()&&rt2!=b._int.rend())
			{
				int tmp=(*rt1-'0')+(*rt2-'0')+flag;
				flag=tmp/10;
				tmp=tmp%10;
				ret._int.insert(0,1,tmp+'0');
				rt2++;
				rt1++;
			}
			while(rt1!=a._int.rend())
			{
				int tmp=(*rt1-'0')+flag;
				flag=tmp/10;
				tmp=tmp%10;
				ret._int.insert(0,1,tmp+'0');
				rt1++;
			}
			while(rt2!=b._int.rend())
			{
				int tmp=(*rt2-'0')+flag;
				flag=tmp/10;
				tmp=tmp%10;
				ret._int.insert(0,1,tmp+'0');
				rt2++;
			}
			if(flag)
				ret._int.insert(0,1,'1');
		}

		if(a._sign!=b._sign)		//异号相加
		{
			Num aa=a,bb=b;
			if(a._abs()b
			string::reverse_iterator rt2=bb._float.rbegin();
			int len1=aa._float.length();
			int len2=bb._float.length();
			while(len1>len2)
			{
				ret._float.insert(0,1,*rt1);
				len1--;
				rt1++;
			}
			while(len10)
				{
					flag=0;
				}
				ret._float.insert(0,1,tmp+'0');
				rt1++;
				rt2++;
				len1--;
				len2--;
			}

			rt1=aa._int.rbegin();//计算整数部分
			rt2=bb._int.rbegin();
			while(rt1!=aa._int.rend()&&rt2!=bb._int.rend())
			{
				int tmp=(*rt1-'0')-(flag+*rt2-'0');
				if(tmp<0)
				{
					flag=1;
					tmp+=10;
				}
				else if(tmp>=0)
				{
					flag=0;
				}
				ret._int.insert(0,1,tmp+'0');
				rt1++;
				rt2++;
			}
			while(rt1!=aa._int.rend())
			{
				int tmp=*rt1-flag;
				if(tmp<0)
				{
					flag=1;
					tmp+=10;
				}
				else if(tmp>=0)
				{
					flag=0;
				}
				ret._int.insert(0,1,*rt1);
				rt1++;
			}
			ret=InputNum(ret._int+'.'+ret._float).second;
		}
		if(a._abs()>b._abs())		//处理符号位
			ret._sign=a._sign;
		else if(a._abs()

减法:

    复用加法

乘法:(初级版本,下期进阶)

    复用加法 如123+456.789

    先计算456个123相加

    再计算7个123相加,并将结果的整数部分最后一位删除,放到小数部分的首位

    再计算8个123相加,并将结果的整数部分最后俩位删除,放到小数部分的首位

    再计算9个123相加,并将结果的整数部分最后三位删除,放到小数部分的首位

    将上面的所有结果相加返回

除法:

    复用减法(初级版本,下期进阶)

    不断做a-b直到a小于等于0

    返回减法次数


缺点:效率低 计算除法的精度只有1


第一版的完整代码

#pragma once
#include 
#include 
using namespace std;

enum SIGN
{
	POSITIVE,
	NEGATIVE
};

class Num
{
protected:
	SIGN _sign;
	string _int;
	string _float;
public:
	Num()
		:_sign(POSITIVE)
	{}

	Num(Num& a)
	{
		_sign=a._sign;
		_int=a._int;
		_float=a._float;
	}

	bool IsZero(Num& a)
	{
		string::iterator it1=a._int.begin();
		string::iterator it2=a._float.begin();
		while(it1!=a._int.end())
		{
		if(*it1!='0')
			return false;
		it1++;
		}
		while(it2!=a._float.end())
		{
		if(*it2!='0')
			return false;
		it2++;
		}
		return true;
	}

	bool IsZero()
	{
		string::iterator it1=_int.begin();
		string::iterator it2=_float.begin();
		while(it1!=_int.end())
		{
		if(*it1!='0')
			return false;
		it1++;
		}
		while(it2!=_float.end())
		{
		if(*it2!='0')
			return false;
		it2++;
		}
		return true;
	}

	bool operator>(Num& a)
	{
		if(IsZero(*this)&&IsZero(a))
			return false;
		if(_sign==NEGATIVE&&a._sign==POSITIVE)
			return false;
		else if(_sign==POSITIVE&&a._sign==NEGATIVE)
			return true;

		if(_sign==POSITIVE&&a._sign==POSITIVE)
		{
			if(_int.length()>a._int.length())
				return true;
			else if(_int.length()0)
					return true;
				else if(strcmp(_int.c_str(),a._int.c_str())==0)
				{
				string::iterator it1=_float.begin();
				string::iterator it2=a._float.begin();

				while(it1!=_float.end()&&it2!=a._float.end())
				{
					if(*it1<*it2)
						return false;
					it1++;
					it2++;
				}
				while(it2!=a._float.end())
				{
					return false;
				}
				while(it1!=_float.end())
				{
					return true;
				}
				}
				return false;
			}
		}

		if(_sign==NEGATIVE&&a._sign==NEGATIVE)
		{
			if(_int.length()>a._int.length())
				return false;
			else if(_int.length()0)
					return false;
				else if(strcmp(_int.c_str(),a._int.c_str())==0)
				{
				string::iterator it1=_float.begin();
				string::iterator it2=a._float.begin();

				while(it1!=_float.end()&&it2!=a._float.end())
				{
					if(*it1<*it2)
						return true;
					else if(*it1>*it2)
						return false;
					it1++;
					it2++;
				}
				while(it1!=_float.end())
				{
					return false;
				}
				while(it2!=a._float.end())
					return true;
				}
				return false;
			}
		}
		return true;
	}

	bool operator==(Num& a)
	{
		if(IsZero(*this)&&IsZero(a))
			return true;
		if(_sign==NEGATIVE&&a._sign==POSITIVE)
			return false;
		else if(_sign==POSITIVE&&a._sign==NEGATIVE)
			return false;

		if(_int.length()!=a._int.length()||_float.length()!=a._float.length())
			return false;
		else if(_int.length()==a._int.length()&&strcmp((_int.c_str()),a._int.c_str())!=0)
			return false;
		else if(_float.length()==a._float.length()&&strcmp((_float.c_str()),a._float.c_str())!=0)
			return false;

		return true;
	}

	bool operator<(Num& a)
	{
	return !(*this>a||*this==a);
	}

	bool operator>=(Num& a)
	{
	return *this>a||*this==a;
	}

	bool operator<=(Num& a)
	{
	return *thislen2)//小数部分
			{
				len1--;
				ret._float.insert(0,1,*rt1);
				rt1++;
			}
			while(len2>len1)
			{
				len2--;
				ret._float.insert(0,1,*rt2);
				rt2++;
			}
			while(len1==len2&&rt1!=a._float.rend()&&rt2!=b._float.rend())
			{
				int tmp=(*rt1-'0')+(*rt2-'0')+flag;
				flag=tmp/10;
				tmp=tmp%10;
				ret._float.insert(0,1,tmp+'0');
				rt2++;
				rt1++;
				len1--;
				len2--;
			}

			rt1=a._int.rbegin();
			rt2=b._int.rbegin();

			while(rt1!=a._int.rend()&&rt2!=b._int.rend())
			{
				int tmp=(*rt1-'0')+(*rt2-'0')+flag;
				flag=tmp/10;
				tmp=tmp%10;
				ret._int.insert(0,1,tmp+'0');
				rt2++;
				rt1++;
			}
			while(rt1!=a._int.rend())
			{
				int tmp=(*rt1-'0')+flag;
				flag=tmp/10;
				tmp=tmp%10;
				ret._int.insert(0,1,tmp+'0');
				rt1++;
			}
			while(rt2!=b._int.rend())
			{
				int tmp=(*rt2-'0')+flag;
				flag=tmp/10;
				tmp=tmp%10;
				ret._int.insert(0,1,tmp+'0');
				rt2++;
			}
			if(flag)
				ret._int.insert(0,1,'1');
		}

		if(a._sign!=b._sign)		//异号相加
		{
			Num aa=a,bb=b;
			if(a._abs()b
			string::reverse_iterator rt2=bb._float.rbegin();
			int len1=aa._float.length();
			int len2=bb._float.length();
			while(len1>len2)
			{
				ret._float.insert(0,1,*rt1);
				len1--;
				rt1++;
			}
			while(len10)
				{
					flag=0;
				}
				ret._float.insert(0,1,tmp+'0');
				rt1++;
				rt2++;
				len1--;
				len2--;
			}

			rt1=aa._int.rbegin();//计算整数部分
			rt2=bb._int.rbegin();
			while(rt1!=aa._int.rend()&&rt2!=bb._int.rend())
			{
				int tmp=(*rt1-'0')-(flag+*rt2-'0');
				if(tmp<0)
				{
					flag=1;
					tmp+=10;
				}
				else if(tmp>=0)
				{
					flag=0;
				}
				ret._int.insert(0,1,tmp+'0');
				rt1++;
				rt2++;
			}
			while(rt1!=aa._int.rend())
			{
				int tmp=*rt1-flag;
				if(tmp<0)
				{
					flag=1;
					tmp+=10;
				}
				else if(tmp>=0)
				{
					flag=0;
				}
				ret._int.insert(0,1,*rt1);
				rt1++;
			}
			ret=InputNum(ret._int+'.'+ret._float).second;
		}
		if(a._abs()>b._abs())		//处理符号位
			ret._sign=a._sign;
		else if(a._abs() InputNum(string& a)
	{
		string tmp;
		int point=0;
		int head=1;
		int flag=1;
		Num ret;
		string::iterator it=a.begin();
		if(a.empty())
			{
				return make_pair(true,ret);
			}
		while(it!=a.end())	//123 +123 -123 .123 0.123 0000.000123  +-=
		{
			if(*it=='-'&&head==1&&flag==1)
			{
				ret._sign=NEGATIVE;
				flag=0;
				it++;
				continue;
			}
			else if(*it=='+'&&head==1&&flag==1)
			{
				it++;
				flag=0;
				continue;
			}
			else if((*it=='+'||*it=='_')&&flag==0)
			{
				return make_pair(false,ret);
			}


			if(*it=='0'&&point==0&&head==1)
			{
			it++;
			continue;
			}

			if(*it=='.'&&point==0)
			{
			point=1;
			head=0;
			it++;
			continue;
			}
			else if(*it=='.'&&point==1)
			{
				return make_pair(false,ret);
			}

			if(*it>'9'||*it<'0')
			{
				return make_pair(false,ret);
			}

			if(*it<='9'&&*it>='0')
			{
				head=0;
				if(point==0)
				{
					ret._int+=*it;
					it++;
				}
				else if(point==1)
				{
					ret._float+=*it;
					it++;
				}
			}
		}
		return make_pair(true,ret);
	}

	friend ostream& operator<<(ostream& cout,Num& a);
};

ostream& operator<<(ostream& cout,Num& a)
{
	if(a.IsZero(a))
	{
	cout<<"0";
	return cout;
	}
	if(a._int.empty()&&a._sign==NEGATIVE)
		cout<<"-0"<<'.'<


你可能感兴趣的:(小项目)