自己写的大数运算,目前只写了加减乘三个操作。负数、小数、除法还在研究当中。。。
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define DEFAULT_BUFF_SIZE 3000
#define SECURITY_BUFF_SIZE 8
using namespace std;
//Kiritow's General class BigNumber. Written on Nov. 14th, 2015
//BigNumber Build 1
//All rights reserved. Nobody is allowed to copy without permission.
class bign
{
private:
int* data;
int data_max;
public:
bign()
{
try
{
data=new int[DEFAULT_BUFF_SIZE];
data_max=DEFAULT_BUFF_SIZE;
set_empty();
}
catch(...)
{
cerr<<"Class BIGN : "<<(void*)this<<" : Cannot get enough memory"<<endl;
data_max=0;
data=nullptr;
}
}
bign(const bign& inc)
{
data_max=inc.data_max;
try
{
data=new int[data_max];
set_empty();
memcpy(data,inc.data,sizeof(int)*data_max);
}
catch(...)
{
cerr<<"Class BIGN : "<<(void*)this<<" : Cannot get enough memory"<<endl;
data_max=0;
data=nullptr;
}
}
bign(long inc)
{
char buff[32];
try
{
//This is a BIG try module, which is not recommend.
//But here we have to write it like this as we don't want any exceptions thrown in constructor
//and we don't know which type to return.
data=new int[DEFAULT_BUFF_SIZE];
data_max=DEFAULT_BUFF_SIZE;
set_empty();
memset(buff,0,32);
sprintf(buff,"%ld",inc);
int len=strlen(buff);
for(int i=len-1;i>=0;i--)
{
data[len-1-i]=buff[i]-'0';
}
}
catch(...)
{
cerr<<"Class BIGN : "<<(void*)this<<" : Cannot get enough memory"<<endl;
data=nullptr;
data_max=0;
}
}
bign(const char* inc)
{
int len=strlen(inc);
data=nullptr;
if(len>DEFAULT_BUFF_SIZE)
{
data_max=len+SECURITY_BUFF_SIZE;
}
else
{
data_max=DEFAULT_BUFF_SIZE;
}
reset_buff_size(data_max);
if(data!=nullptr)
{
for(int i=len-1; i>=0; i--)
{
data[len-1-i]=inc[i]-'0';
}
}
}
~bign()
{
if(data!=nullptr)
{
delete[] data;
}
}
char* convert_to_str(char* str)
{
int lenx=len();
for(int i=lenx-1;i>=0;i--)
{
str[lenx-i-1]=data[i]+'0';
}
return str;
}
bool can_be_converted_to_long()
{
int thislen=len();
if(thislen<10)
{
return true;
}
else if (thislen==10)
{
bign tmp(2147438647);
return *this<tmp;
}
else
{
return false;
}
}
operator long() throw(const char*)
{
if(can_be_converted_to_long())
{
char buff[32];
memset(buff,0,32);
int length=len();
for(int i=0;i<length;i++)
{
buff[length-i-1]=data[i];
}
long tmp;
sscanf(buff,"%ld",&tmp);
return tmp;
}
else
{
throw "BIGN::operator long int() : cannot convert to type long";
}
}
void set_empty()
{
memset(data,0,sizeof(int)*data_max);
}
int len() const
{
for(int i=data_max-1;i>=0;i--)
{
if(data[i]!=0)
{
return i+1;
}
}
return 0;
}
int reset_buff_size(int NewBuffSize)
{
if(data!=nullptr) delete[] data;
try
{
data=new int[NewBuffSize];
data_max=NewBuffSize;
set_empty();
}
catch(...)
{
data=nullptr;
data_max=0;
cerr<<"Class BIGN : "<<(void*)this<<" : Cannot get enough memory"<<endl;
return -1;
}
return 0;
}
bool operator < (const bign& inc) const
{
if(this==&inc) return false;
int lena=len();
int lenb=inc.len();
if(lena<lenb)
{
return true;
}
else if(lenb>lena)
{
return false;
}
else
{
for(int i=lena-1;i>=0;i--)
{
if(data[i]<inc.data[i])
{
return true;
}
else if(data[i]>inc.data[i])
{
return false;
}
}
return false;
}
}
bool operator > (const bign& inc) const
{
if(this==&inc) return false;
int lena=len();
int lenb=inc.len();
if(lena<lenb)
{
return false;
}
else if(lenb>lena)
{
return true;
}
else
{
for(int i=lena-1;i>=0;i--)
{
if(data[i]<inc.data[i])
{
return false;
}
else if(data[i]>inc.data[i])
{
return true;
}
}
return false;
}
}
bool operator == (const bign& inc) const
{
if(this==&inc) return true;
int lena=len();
int lenb=inc.len();
if(lena!=lenb)
{
return false;
}
else
{
for(int i=lena-1;i>=0;i--)
{
if(data[i]!=inc.data[i])
{
return false;
}
}
return true;
}
}
bool operator >= (const bign& inc) const
{
return (*this>inc)&&(*this==inc);
}
bool operator <= (const bign& inc) const
{
return (*this<inc)&&(*this==inc);
}
bign& operator = (const bign& inc)
{
if(this==&inc) return *this;
if(inc.data_max>data_max)
{
reset_buff_size(inc.data_max);
}
for(int i=0;i<inc.data_max;i++)
{
data[i]=inc.data[i];
}
return *this;
}
friend bign operator + (const bign& a,const bign& b);
friend bign operator - (const bign& a,const bign& b);
friend bign operator * (const bign& a,const bign& b);
};
bign operator + (const bign& a ,const bign& b)
{
bign tmp;
int maxsize=(a.data_max>b.data_max)?(a.data_max):(b.data_max);
if(maxsize>tmp.data_max)
{
tmp.reset_buff_size(maxsize);
}
int maxlen=(a.len()>b.len())?(a.len()):(b.len());
for(int i=0;i<maxlen;i++)
{
tmp.data[i]+=a.data[i]+b.data[i];
if(tmp.data[i]>9)
{
tmp.data[i]-=10;
tmp.data[i+1]++;
}
}
return tmp;
}
bign operator - (const bign& a,const bign& b)
{
bign tmp;
int maxsize=(a.data_max>b.data_max)?(a.data_max):(b.data_max);
if(maxsize>tmp.data_max)
{
tmp.reset_buff_size(maxsize);
}
int maxlen=(a.len()>b.len())?(a.len()):(b.len());
if(a>b)
{
for(int i=0;i<maxlen;i++)
{
tmp.data[i]+=a.data[i]-b.data[i];
if(tmp.data[i]<0)
{
tmp.data[i]+=10;
tmp.data[i+1]--;
}
}
}
else if(a<b)
{
for(int i=0;i<maxlen;i++)
{
tmp.data[i]+=b.data[i]-a.data[i];
if(tmp.data[i]<0)
{
tmp.data[i]+=10;
tmp.data[i+1]--;
}
}
}
return tmp;
}
bign operator * (const bign& a,const bign& b)
{
bign tmp;
int lena=a.len();
int lenb=b.len();
if(tmp.data_max<lena+lenb+1)
{
tmp.reset_buff_size(lena+lenb+1);
}
for(int i=0;i<lena;i++)
{
for(int j=0;j<lenb;j++)
{
tmp.data[i+j]+=a.data[i]*b.data[j];
}
}
for(int i=0;i<tmp.data_max-1;i++)
{
if(tmp.data[i]>9)
{
tmp.data[i+1]+=tmp.data[i]/10;
tmp.data[i]=tmp.data[i]%10;
}
}
return tmp;
}
char buff[3000];
int main()
{
bign a("1234"),b("5678");
a=a+b;
printf("%s\n",a.convert_to_str(buff));
return 0;
}
在写的时候参考了一下string的设计,之前operator都是以成员函数重载的,所以这样的操作
bign a,b;
a+b;
a+b的时候就会直接把结果存入a中,然而并不一定符合本意。
所以就改成了友元函数,并且返回值而不是引用。