上一篇实现了大数加法,乘除法都是简单的复用加法,这样做时间复杂度高,精度低。
进阶:
1.乘法模拟竖式计算方法 核心思路是num1[i]*num2[j]的结果一定对应乘积中的[i+j]位,并且考虑对[i+j+1]位的进位。
这样的时间复杂度为O(m*n) 而简单的复用加法的时间复杂度为 (q/p)*(n+m)其中q,p为大数的实际值,n,m为大数的位数,这样当p很小的时候,时间复杂度会很大。进一步优化的方法是使用FFT即快速傅里叶变换。下一篇中进行升级。
Num by(Num& a,Num&b)
{
Num ret;
int pos1=a._float.length();
int pos2=b._float.length();
string s1,s2,s(1000,'0');
s1=a._int+a._float;
s2=b._int+b._float;
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
for(int i=0;i0)
{
ret._float.insert(0,1,*rts);
rts++;
len--;
}
if(a._sign==b._sign)
ret._sign=POSITIVE;
else
ret._sign=NEGATIVE;
ret._int=ret.InputNum(ret._int).second._int;
return ret;
}
2.除法模拟竖式计算。为满足浮点计算,引入新的标志:精度。每一个大数对象都拥有一个进度,在运算除法时,返回的结果精度由被除数的精度,除数的小数位数共同决定。
核心算法为大数除以整数。处理两个浮点大数相除的时候,将两个大数的小数位对齐到整数位,记录对齐位数。将被除数的整数位额外对齐 10e精度 倍。计算结束后,取结果的0~精度-1为整数位,精度~end为小数位 处理符号位后返回计算结果。
Num except(Num& a,Num& b)
{
int len1=a._float.length();
int len2=b._float.length();
int _precision=a._pos;
string aa=a._int+a._float;
string bb=b._int+b._float;
string tmp;
string ans;
Num cop1,cop2,ret;
int ok=0;
for(int i=0;i=cop2)
{
ok=1;
int ex=(_exc(tmp,bb));
ans+=(ex+'0');
//char arr[3]={0};
//itoa(ex,arr,10);
Num ttmp;
ttmp._int+=ex+'0';
tmp=reduce(cop1,by(cop2,ttmp))._int;
}
else/* if(ok==1)*/
{
ans+='0';
}
}
/*****************************核心算法****事实上要处理除数是字符串,以及提高运算精度等问题**********
// for(int i=0;i=x)
// {
// ok=1;
// ans+=(cmp/x+'0');
// cmp%=x;
// }
// else{
// ans+='0';
// }
// }
******************************************************************************************/
string::iterator it=ans.begin();
int intlen=ans.length()-_precision;
while(it!=ans.end()&&intlen>0)
{
ret._int+=*it;
it++;
intlen--;
}
string::reverse_iterator rt1=ans.rbegin();
while(_precision>0&&rt1!=ans.rend())
{
ret._float.insert(0,1,*rt1);
rt1++;
_precision--;
}
while(_precision>0)
{
ret._float.insert(0,1,'0');
_precision--;
}
ret._int=InputNum(ret._int).second._int;
return ret;
}
int _exc(string& a,string& b)
{
int len1=a.length();
int len2=b.length();
int ret=0;
Num bb;
Num tmp1,tmp2;
bb._int=b;
tmp1._int=a;
tmp2._int=b;
if(tmp1=tmp2)
{
ret++;
tmp2=tmp2.add(tmp2,bb);
}
return ret;
}
完整代码
#pragma once
#include
#include
#include
#define POS 10 //精度
using namespace std;
enum SIGN
{
POSITIVE,
NEGATIVE
};
typedef class Num
{
protected:
SIGN _sign;
string _int;
string _float;
int _pos;//精度
public:
Num()
:_sign(POSITIVE),
_pos(POS)
{}
Num(Num& a)
{
_sign=a._sign;
_int=a._int;
_float=a._float;
_pos=a._pos;
}
int precision(int x)
{
_pos=x;
return _pos;
}
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-'0';
if(tmp<0)
{
flag=1;
tmp+=10;
}
else if(tmp>=0)
{
flag=0;
}
ret._int.insert(0,1,tmp+'0');
rt1++;
}
ret=InputNum(ret._int+'.'+ret._float).second;
}
if(a._abs()>b._abs()) //处理符号位
ret._sign=a._sign;
else if(a._abs()0)
{
ret._float.insert(0,1,*rts);
rts++;
len--;
}
if(a._sign==b._sign)
ret._sign=POSITIVE;
else
ret._sign=NEGATIVE;
ret._int=ret.InputNum(ret._int).second._int;
return ret;
}
Num except(Num& a,Num& b)
{
int len1=a._float.length();
int len2=b._float.length();
int _precision=a._pos;
string aa=a._int+a._float;
string bb=b._int+b._float;
string tmp;
string ans;
Num cop1,cop2,ret;
int ok=0;
for(int i=0;i=cop2)
{
ok=1;
int ex=(_exc(tmp,bb));
ans+=(ex+'0');
//char arr[3]={0};
//itoa(ex,arr,10);
Num ttmp;
ttmp._int+=ex+'0';
tmp=reduce(cop1,by(cop2,ttmp))._int;
}
else/* if(ok==1)*/
{
ans+='0';
}
}
string::iterator it=ans.begin();
int intlen=ans.length()-_precision;
while(it!=ans.end()&&intlen>0)
{
ret._int+=*it;
it++;
intlen--;
}
string::reverse_iterator rt1=ans.rbegin();
while(_precision>0&&rt1!=ans.rend())
{
ret._float.insert(0,1,*rt1);
rt1++;
_precision--;
}
while(_precision>0)
{
ret._float.insert(0,1,'0');
_precision--;
}
ret._int=InputNum(ret._int).second._int;
return ret;
}
int _exc(string& a,string& b)
{
int len1=a.length();
int len2=b.length();
int ret=0;
Num bb;
Num tmp1,tmp2;
bb._int=b;
tmp1._int=a;
tmp2._int=b;
if(tmp1=tmp2)
{
ret++;
tmp2=tmp2.add(tmp2,bb);
}
return ret;
}
pair 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);
}lfloat;
ostream& operator<<(ostream& cout,Num& a)
{
if(a.IsZero(a))
{
cout<<"0";
return cout;
}
if(a._int.empty()&&a._sign==NEGATIVE)
cout<<"-0"<<'.'<
这样就得到了支持四则运算,支出修改除法精度的一个类 (lfloat)
下一篇优化乘法,缩减冗余代码,并实现运算表达式计算。