?? 3.txt
字號:
基本算法:
大整數運算的基本算法比較簡單,很多書上都有介紹,本文有一點要說明,本文采用的是萬進制來運算。為什么采用萬進制?因為萬進制一個int字長可容納4數字,這樣就減少存儲空間,同時大大提高了運算速度。照此說法還不如采用億進制,原因在于乘法運算的過程中需要用到兩個數相乘,而兩個小于一萬的數相乘小于一億,也小于21億,符合一個int字長,而采用億進制會造成越界,處理起來麻煩,費時。
次方運算采用了優化算法,實際上采用的是將指數化成二進制,然后拆開運算后相加得到結果。
階乘運算基本未使用優化策略,采用傳統的遞推算法。
代碼:
//
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
class BigInt
{
private:
int sign;
int nb;
int *pData;
void Init(int nnb);
void ShowData(int m);
public:
BigInt();
BigInt(BigInt &bnum);
BigInt(int num);
~BigInt();
void Show();//控制臺顯示
void trim();//規范化
BigInt &operator=(int num);
BigInt &operator=(BigInt &bnum);
int operator==(BigInt &bnum);
int operator!=(BigInt &bnum);
int operator>(BigInt &bnum);
int operator<(BigInt &bnum);
int operator>=(BigInt &bnum);
int operator<=(BigInt &bnum);
BigInt &operator+=(BigInt &bnum);
BigInt &operator-=(BigInt &bnum);
BigInt &operator*=(BigInt &bnum);
int GetBit();//獲取位數
int GetSign();//獲取符號
void Cont();//相反數
int ReadFromStr(char *str);//數字字符串轉換為BigInt
int WriteToStr(char *str);//轉變為字符串
friend BigInt operator-(BigInt &bnum);
};
BigInt::BigInt()
{
sign=0;
nb=1;
pData=new int[nb];
pData[0]=0;
}
BigInt::BigInt(BigInt &bnum)
{
sign=bnum.sign;
nb=bnum.nb;
pData=new int[nb];
for(int i=0;i<nb;i++)
pData[i]=bnum.pData[i];
}
BigInt::BigInt(int num)
{
*this=num;
}
BigInt::~BigInt()
{
delete []pData;
}
void BigInt::Init(int nnb)
{
delete []pData;
nb=nnb;
pData=new int[nb];
for(int i=0;i<nb;i++)
pData[i]=0;
}
void BigInt::ShowData(int m)
{
printf("%c%c%c%c",pData[m]/1000+'0',(pData[m]%1000)/100+'0',(pData[m]%100)/10+'0',pData[m]%10+'0');
}
void BigInt::Show()//控制臺顯示
{
int i;
if(sign==-1)
printf("-");
for(i=nb-1;i>=0;i--)
{
ShowData(i);
}
}
void BigInt::trim()//規范化
{
int i,j;
for(i=nb-1;i>0;i--)
{
if(pData[i]!=0)
break;
}
if(i==nb-1)
return;
BigInt bnum=*this;
Init(i+1);
for(j=0;j<=i;j++)
{
pData[j]=bnum.pData[j];
}
}
BigInt &BigInt::operator=(int num)
{
int n=abs(num);
if(num==0)
sign=0;
else if(num>0)
sign=1;
else
sign=-1;
if(n<10000)
{
Init(1);
pData[0]=n;
}
else if(n<100000000)
{
Init(2);
pData[1]=n/10000;
pData[0]=n%10000;
}
else
{
Init(3);
pData[2]=n/100000000;
pData[1]=(n%100000000)/10000;
pData[0]=n%10000;
}
return *this;
}
BigInt &BigInt::operator=(BigInt &bnum)
{
int i;
if(this==&bnum)
return *this;
sign=bnum.sign;
nb=bnum.nb;
Init(nb);
for(i=0;i<nb;i++)
{
pData[i]=bnum.pData[i];
}
return *this;
}
int BigInt::operator==(BigInt &bnum)
{
if(this==&bnum)
return 1;
if(sign!=bnum.sign)
return 0;
trim();
bnum.trim();
if(nb!=bnum.nb)
return 0;
for(int i=0;i<nb;i++)
{
if(pData[i]!=bnum.pData[i])
return 0;
}
return 1;
}
int BigInt::operator!=(BigInt &bnum)
{
return !(*this==bnum);
}
int BigInt::operator>(BigInt &bnum)
{
if(this==&bnum)
return 0;
if(sign>bnum.sign)
return 1;
if(sign<bnum.sign)
return 0;
if(sign==0)
return 0;
trim();
bnum.trim();
if(nb>bnum.nb)
{
if(sign>0)
return 1;
else
return 0;
}
if(nb<bnum.nb)
{
if(sign>0)
return 0;
else
return 1;
}
for(int i=nb-1;i>=0;i--)
{
if(pData[i]>bnum.pData[i])
{
if(sign>0)
return 1;
else
return 0;
}
else if(pData[i]<bnum.pData[i])
{
if(sign>0)
return 0;
else
return 1;
}
}
return 0;
}
int BigInt::operator<(BigInt &bnum)
{
return bnum>(*this);
}
int BigInt::operator>=(BigInt &bnum)
{
return *this==bnum||*this>bnum;
}
int BigInt::operator<=(BigInt &bnum)
{
return *this==bnum||*this<bnum;
}
///////////////////////////////////////////////////////////////
BigInt operator+(BigInt &bnum1,BigInt &bnum2)
{
BigInt bnum3;
bnum3=bnum1;
bnum3+=bnum2;
return BigInt(bnum3);
}
BigInt operator-(BigInt &bnum1,BigInt &bnum2)
{
BigInt bnum3;
bnum3=bnum1;
bnum3-=bnum2;
return BigInt(bnum3);
}
BigInt operator*(BigInt &bnum1,BigInt &bnum2)
{
BigInt bnum3;
bnum3=bnum1;
bnum3*=bnum2;
return BigInt(bnum3);
}
////////////////////////////////////////////////////////////////
BigInt &BigInt::operator+=(BigInt &bnum)
{
if(this==&bnum)
{
BigInt bnum1=bnum;
*this=bnum1+bnum1;
return *this;
}
if(sign==0)
{
return bnum;
}
if(bnum.sign==0)
{
return *this;
}
int i,m;
BigInt bnum0,*p1,*p2;
if(sign<0&&bnum.sign<0)
{
this->sign=1;
bnum0=bnum;
bnum0.sign=1;
*this+=bnum0;
this->sign=-1;
return *this;
}
if(sign>0&&bnum.sign<0)
{
bnum0=bnum;
bnum0.sign=1;
*this-=bnum0;
return *this;
}
if(sign<0&&bnum.sign>0)
{
this->sign=1;
bnum0=bnum;
bnum0.sign=1;
*this-=bnum0;
this->sign=-1;
return *this;
}
bnum0=*this;
if(bnum.nb>bnum0.nb)
{
m=bnum.nb;
p1=&bnum;
p2=&bnum0;
}
else
{
m=bnum0.nb;
p1=&bnum0;
p2=&bnum;
}
if(p1->nb==p2->nb&&(p1->pData[m-1]+p2->pData[m-1])>=9999)
Init(m+1);
else if(p1->pData[m-1]>=9999)
Init(m+1);
else
Init(m);
sign=1;
for(i=0;i<p2->nb;i++)
{
pData[i]=p1->pData[i]+p2->pData[i];
}
for(;i<p1->nb;i++)
pData[i]=p1->pData[i];
for(i=0;i<nb;i++)
{
if(pData[i]>=10000)
{
//pData[i+1]=pData[i+1]+pData[i]/10000;
pData[i+1]+=1;
pData[i]=pData[i]%10000;
}
}
return *this;
}
BigInt &BigInt::operator-=(BigInt &bnum)
{
if(this==&bnum||*this==bnum)
{
*this=0;
return *this;
}
int i,m;
BigInt bnum0,*p1,*p2;
if(sign<0&&bnum.sign<0)
{
this->sign=1;
bnum0=bnum;
bnum0.sign=1;
*this=bnum0-*this;
return *this;
}
if(sign>0&&bnum.sign<0)
{
bnum0=bnum;
bnum0.sign=1;
*this+=bnum0;
return *this;
}
if(sign<0&&bnum.sign>0)
{
this->sign=1;
*this+=bnum;
this->sign=-1;
return *this;
}
bnum0=*this;
if(bnum0>bnum)
{
m=bnum0.nb;
p1=&bnum0;
p2=&bnum;
Init(m);
sign=1;
}
else
{
m=bnum.nb;
p1=&bnum;
p2=&bnum0;
Init(m);
sign=-1;
}
for(i=0;i<p2->nb;i++)
{
pData[i]=p1->pData[i]-p2->pData[i];
}
for(;i<p1->nb;i++)
pData[i]=p1->pData[i];
for(i=0;i<nb;i++)
{
if(pData[i]<0)
{
pData[i]+=10000;
pData[i+1]-=1;
}
}
return *this;
}
BigInt &BigInt::operator*=(BigInt &bnum)
{
if(this==&bnum)
{
BigInt bnum1=bnum;
*this=bnum1*bnum1;
return *this;
}
if(sign==0||bnum.sign==0)
{
*this=0;
return *this;
}
int i,j,d=0,*temp;
BigInt bnum0;
bnum0=*this;
temp=new int[bnum0.nb+1];
Init(bnum0.nb+bnum.nb);
sign=bnum0.sign*bnum.sign;
for(i=0;i<bnum.nb;i++)
{
temp[bnum0.nb]=0;
for(j=0;j<bnum0.nb;j++)
{
temp[j]=bnum0.pData[j]*bnum.pData[i];
}
for(j=0;j<bnum0.nb;j++)
{
if(temp[j]>=10000)
{
temp[j+1]=temp[j+1]+temp[j]/10000;
temp[j]=temp[j]%10000;
}
}
for(j=0;j<=bnum0.nb;j++)
{
pData[j+d]+=temp[j];
}
d++;
}
for(j=0;j<nb;j++)
{
if(pData[j]>=10000)
{
pData[j+1]=pData[j+1]+pData[j]/10000;
pData[j]=pData[j]%10000;
}
}
delete []temp;
return *this;
}
int BigInt::GetBit()//獲取位數
{
int b;
trim();
b=(nb-1)*4;
if(pData[nb-1]>=1000)
b+=4;
else if(pData[nb-1]>=100)
b+=3;
else if(pData[nb-1]>=10)
b+=2;
else
b+=1;
return b;
}
int BigInt::GetSign()//獲取符號
{
return sign;
}
int BigInt::ReadFromStr(char *str)//數字字符串轉換為BigInt
{
int i,j,len=strlen(str),sg=0,t;
if(str[0]=='-')
{
sg=-1;
}
else if(str[0]=='+')
{
sg=1;
}
for(i=abs(sg);i<len;i++)
{
if(str[i]<'0'||str[i]>'9')
return 0;
}
j=abs(sg);
while(j<len)
{
if(str[j]!='0')
break;
j++;
}
if(len==j)
{
Init(1);
return 1;
}
if((len-j)%4==0)
{
Init((len-j)/4);
for(i=0;i<nb;i++)
{
t=4*i+1;
pData[i]=(str[len-t]-'0')+(str[len-t-1]-'0')*10+(str[len-t-2]-'0')*100+(str[len-t-3]-'0')*1000;
}
}
else
{
Init((len-j)/4+1);
for(i=0;i<nb-1;i++)
{
t=4*i+1;
pData[i]=(str[len-t]-'0')+(str[len-t-1]-'0')*10+(str[len-t-2]-'0')*100+(str[len-t-3]-'0')*1000;
}
i=abs(sg);
if((len-j)%4==1)
pData[nb-1]=str[i+0]-'0';
else if((len-j)%4==2)
pData[nb-1]=(str[i+0]-'0')*10+(str[i+1]-'0');
else
pData[nb-1]=(str[i+0]-'0')*100+(str[i+1]-'0')*10+str[i+2]-'0';
}
if(sg<0)
sign=-1;
else
sign=1;
return nb;
}
int BigInt::WriteToStr(char *str)//轉變為字符串
{
int i,len,k;
trim();
k=pData[nb-1];
if(sign<0)
k*=-1;
itoa(k,str,10);
len=strlen(str);
for(i=nb-2;i>=0;i--)
{
k=nb-2-i;
str[len+4*i]=pData[k]/1000+'0';
str[len+4*i+1]=(pData[k]%1000)/100+'0';
str[len+4*i+2]=(pData[k]%100)/10+'0';
str[len+4*i+3]=pData[k]%10+'0';
}
len=GetBit();
if(sign<0)
len++;
str[len]='\0';
return len;
}
void BigInt::Cont()//相反數
{
sign*=-1;
}
BigInt operator-(BigInt &bnum)
{
BigInt bnum0;
bnum0=bnum;
bnum0.sign*=-1;
return BigInt(bnum0);
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
BigInt Bfac(int m)//階乘
{
BigInt n1,n2;
n2=1;
for(int i=2;i<=m;i++)
{
n1=i;
n2*=n1;
n2.trim();
}
return BigInt(n2);
}
////////////////////////////////////////////////////////////////
int Pow(int x,int n)//x的n次方
{
if(n==0)
return 1;
if(n<0)
return 0;
int k=n,t,s;
t=x;
s=1;
while(1)
{
if(k%2==1)
{
s*=t;
}
k=k>>1;
if(k==0)
break;
t=t*t;
}
return s;
}
BigInt BPow(BigInt &x,int n)//x的n次方
{
if(n==0)
return 1;
if(n<0)
return 0;
int k=n;
BigInt t,s;
t=x;
s=1;
while(1)
{
if(k%2==1)
{
s*=t;
}
k=k>>1;
if(k==0)
break;
t=t*t;
}
return BigInt(s);
}
BigInt BPow(int x,int n)//x的n次方
{
BigInt c;
if(n==1)
{
c=x;
return BigInt(c);
}
if(n==2)
{
c=x*x;
return BigInt(c);
}
if(n==3)
{
c=x*x*x;
return BigInt(c);
}
double n1=log(2147483647),n2=log(x);
int m=(int)(log(2147483647)/log(x));
if(m>=n)
{
c=(int)pow(x,n);
return BigInt(c);
}
int div=n/m,mod=n%m;
BigInt s;
c=(int)pow(x,m);
s=BPow(c,div);
c=(int)pow(x,mod);
s*=c;
return BigInt(s);
}
////////////////////////////////////////////////////////////////
int main()
{
int i,j,s;
clock_t t_begin,t_end;
BigInt a,b,c,d,e;
a=954654411;
b=1921412412;
c=1921412412;
c.ReadFromStr("4353452543532542542542123456789");c.Show();printf("\n");
char str[200];
b.WriteToStr(str);
printf("%s\n",str);
d=c-a;
//d=d+c;
d.Show();
printf("\n%d\n",d.GetBit());
//printf("\n");
c=a+b+b;
t_begin=clock();
for(i=0;i<10000;i++)
c+=b;
t_end=clock();
printf("代碼所用的時間:%.3f秒\n",(double)(t_end-t_begin)/CLOCKS_PER_SEC);
c.Show();
printf("\n");
t_begin=clock();
e=Bfac(1000);
t_end=clock();
printf("%d\n",e.GetBit());
printf("代碼所用的時間:%.3f秒\n",(double)(t_end-t_begin)/CLOCKS_PER_SEC);
e.trim();
e.Show();
printf("\n");
return 0;
}
本文除法運算未提供,原因在于未找到高效的算法,現在基本思路是,先將大整數近似為double型或者long double,進行除法后,被除數減去乘數與近似近似商(整數)的積,得到一個新的大整數,用此大整數按照前面的步驟進行循環運算,直到不斷得到新的大整數小于除數(此時即為余數),商就為各此近似商之和。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -