上一篇实现了大数加法,乘除法都是简单的复用加法,这样做时间复杂度高,精度低。
进阶:
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;i<s1.length();i++)
for(int j=0;j<s2.length();j++)
{
int temp=(s1[i]-'0')*(s2[j]-'0');
s[i+j+1]=s[i+j+1]-'0'+(s[i+j]-'0'+temp)/10+'0';
s[i+j]=(s[i+j]-'0'+temp)%10+'0';
}
reverse(s.begin(),s.end());
ret._int=s;
int pos=s.length()-pos1-pos2+1;
ret._int.resize(pos);
ret._int[pos-1]='\0';
int len=pos1+pos2;
string::reverse_iterator rts=s.rbegin();
while(rts!=s.rend()&&len>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;
}
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<len1;i++)
{
bb+='0';
}
for(int i=0;i<len2+_precision;i++)
{
aa+='0';
}
cop2._int=bb;
for(int i=0;i<aa.size();i++)
{
tmp+=aa[i];
cop1._int=tmp;
if(cop1>=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<s.size();i++)
// {
// cmp=(cmp*10+s[i]-'0');
// if(cmp>=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