今天看了《算法競賽和入門基礎》中的大整數類後,我自己也試着去實現一個大整數類,並且完成了整數的四則運算和邏輯運算功能。學習到了很多東西。在此分享一下。代碼是C++的。用了C++中的STL模板類vector。
大整數類的數據存儲結構如下所示:
static const int BASE=100000000;
static const int WIDTH=8;
std::vector<int> s;
下面我在書裏原有的基礎上繼續編寫了乘除和減法的代碼。
class BigInteger
{
public:
//數據存儲結構
static const int BASE=100000000;
static const int WIDTH=8;
std::vector<int> s;
//構造函數
BigInteger(long long num=0)
{
*this=num;
}
//long long型整數賦值方法
BigInteger operator = (long long num)
{
s.clear();
do{
s.push_back(num%BASE);
num/=BASE;
}while(num);
return *this;
}
//string類型賦值方法
BigInteger operator = (const std::string &str)
{
s.clear();
int x,len=(str.length()-1)/WIDTH+1;
for(int i=0;i<len;i++)
{
//從尾部開始切割
int end=str.length()-i*WIDTH;
int start=std::max(0,end-WIDTH);
//用sscnaf會去除前導零,下面輸出的時候要注意,不過書裏代碼都已經給出了,這裏我代爲說明一下。
sscanf(str.substr(start,end-start).c_str(),"%d",&x);
s.push_back(x);
}
return *this;
}
//加法
BigInteger operator + (const BigInteger& b) const
{
BigInteger c;
c.s.clear();
for(int i=0,g=0;;i++)
{
if(g==0&&i>=s.size()&&i>=b.s.size())
break;
int x=g;
if(i<s.size())
x+=s[i];
if(i<b.s.size())
x+=b.s[i];
c.s.push_back(x%BASE);
g=x/BASE;
}
return c;
}
BigInteger operator += (const BigInteger& b)
{
*this=*this+b;
return *this;
}
//仿照加法寫的減法,需要注意的是隻需在最前面加負號
BigInteger operator - (const BigInteger& b) const
{
BigInteger c;
c.s.clear();
int MAX=std::max(s.size(),b.s.size());
for(int i=0,g=0;;i++)
{
if(g==0&&i>=MAX)
break;
int x=g;
if(i<s.size())
x+=s[i];
if(i<b.s.size())
x-=b.s[i];
//!!!!!!
if(i==MAX-1)
c.s.push_back(x%BASE);
else
c.s.push_back(abs(x%BASE));
//!!!!!!
g=x/BASE;
}
return c;
}
BigInteger operator -= (const BigInteger& b)
{
*this=*this-b;
return *this;
}
//自己寫的,效率有點低,我把vector中的數全部轉化爲一個整體的string類型,再進行乘法操作,這是我最先想到的寫法。
BigInteger operator * (const BigInteger& b)
{
std::stringstream ss;
for(int i=s.size()-1;i>=0;i--)
ss<<s[i];
std::string operand1=ss.str();
ss.str("");
for(int i=b.s.size()-1;i>=0;i--)
ss<<b.s[i];
std::string operand2=ss.str();
//將string中的一個個數轉爲int型的數
std::vector<int> c,d,temp;
for(int i=operand1.length()-1;i>=0;i--)
c.push_back(operand1[i]-'0');
for(int i=operand2.length()-1;i>=0;i--)
d.push_back(operand2[i]-'0');
int MAX=std::max(c.size(),d.size());
for(int i=0;i<MAX*2+1;i++)
temp.push_back(0);
for(int i=0;i<c.size();i++)
for(int j=0;j<d.size();j++)
temp[i+j]+=c[i]*d[j];
for(int i=0;i<2*MAX+1;i++)
if(temp[i]>9)
{
temp[i+1]+=temp[i]/10;
temp[i]%=10;
}
int m=2*MAX;
while(temp[m]==0)
m--;
BigInteger another;
another.s.clear();
int len=(m-1)/WIDTH+1;
for(int i=0;i<len;i++)
another.s.push_back(0);
for(int i=0;i<len;i++)
{
int x=1;
int k=0;
int end=std::min(m+1,(i+1)*WIDTH);
int start=i*WIDTH;
for(int j=start;j<end;j++)
{
k+=x*temp[j];
x*=10;
}
another.s[i]=k;
}
return another;
}
BigInteger operator *= (const BigInteger& b)
{
*this=*this*b;
return *this;
}
//自己寫的除法,可以實現像int型一樣的效果
BigInteger operator / (const BigInteger& b)
{
std::string operand1,operand2,result;
std::stringstream ss;
for(int i=s.size()-1;i>=0;i--)
ss<<s[i];
operand1=ss.str();
ss.str("");
for(int i=b.s.size()-1;i>=0;i--)
ss<<b.s[i];
operand2=ss.str();
int len1,len2;
len1=operand1.length();
len2=operand2.length();
if(len1<len2) //若操作數1小於操作數2,返回0
return 0;
if(*this==b) //若兩數相等,返回1,這裏用到下面的“==”重載運算符
return 1;
std::vector<int> c,d;
for(int i=0;i<len1;i++)
{
c.push_back(operand1[i]-'0');
if(i<len2)
d.push_back(operand2[i]-'0');
else
d.push_back(0);
}
int time=len1-len2;
int len=len1;
int k,l=0;
for(int i=0;i<=time;i++)
{
int ok=1;
k=0;
do{
if(c[l]==0)
{
l++;
ok=0;
len1--;
}
if(len==len1)
{
int j=0;
while(j<len2)
{
if(c[i+j]>d[j]) //第一次大就表示operand1 > operand2
{
ok=1;
break;
}
else if(c[i+j]<d[j]) //第一次小就表示operand1 < operand2
{
ok=0;
break;
}
j++;
}
}
if(ok)
{
for(int j=0;j<len;j++)
{
c[j+i]-=d[j];
if(c[j+i]<0)
{
c[j+i-1]--;
c[j+i]+=10;
}
}
k++;
}
}while(ok);
len--;
result+=k+'0';
}
BigInteger temp;
temp=result;
return temp;
}
BigInteger operator /= (const BigInteger& b)
{
*this=*this/b;
return *this;
}
//以下的重載方法全都在上面的四則運算上編寫,不再介紹
BigInteger operator % (const BigInteger& b)
{
BigInteger c;
c=*this-(*this/b)*b;
return c;
}
BigInteger operator %= (const BigInteger& b)
{
*this=*this%b;
return *this;
}
bool operator < (const BigInteger& b) const
{
if(s.size()!=b.s.size())
return s.size()<b.s.size();
for(int i=s.size()-1;i>=0;i--)
if(s[i]!=b.s[i])
return s[i]<b.s[i];
return false;
}
bool operator > (const BigInteger& b) const
{
return b<*this;
}
bool operator <= (const BigInteger& b) const
{
return !(b<*this);
}
bool operator >= (const BigInteger& b) const
{
return !(*this<b);
}
bool operator != (const BigInteger& b) const
{
return *this<b||*this>b;
}
bool operator == (const BigInteger& b) const
{
return !(*this<b)&&!(*this>b);
}
friend std::ostream& operator << (std::ostream& out,const BigInteger& x)
{
out<<x.s.back();
for(int i=x.s.size()-2;i>=0;i--)
{
char buf[20];
sprintf(buf,"%08d",x.s[i]);
for(int j=0;j<strlen(buf);j++)
out<<buf[j];
}
return out;
}
friend std::istream& operator >> (std::istream& in,BigInteger& x)
{
std::string s;
if(!(in>>s))
return in;
x=s;
return in;
}
};
全部貼出來是因爲我太懶了,見諒啊。
大整數類除了這個實現,如果大家還有其他實現方法,不妨也分享一下,這裏寫出來只是拋磚引玉。
參考書籍:《算法競賽和入門經典》。