为实现一个不会溢出的四则运算计算器,我们需要将数据存入字符串中,并自己实现加减乘除的逻辑。
存储结构设计:
为了方便计算,将符号位,整数部分,小数部分分别存储
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"<<'.'<