对与基本的运算由于数据类型存储空间有限导致运算结果较大时容易计算溢出,这里通过引入数字数组定义适用于高精度运算的bign类实现大数运算的精确表示,包括常见的赋值/比较/四则运算:
#include<string>
#include<iostream>
#include<cmath>
#include<cstring>
#define MAX_L 2005
using namespace std;
class bign{
public:
int len;
int s[MAX_L];
bign();
bign(const char*);
bign(int);
bool sign;//1 is positive
string to_str()const;
friend istream& operator>>(istream &,bign &);
friend ostream& operator<<(ostream &,bign &);
//重载复制
bign operator=(const char *);
bign operator=(int);
bign operator=(const string);
//重载比较
bool operator>(const bign &)const;
bool operator>=(const bign &)const;
bool operator<(const bign &)const;
bool operator<=(const bign &)const;
bool operator==(const bign &)const;
bool operator!=(const bign &)const;
//四则运算重载
bign operator+(const bign &)const;
bign operator++();
bign operator++(int);
bign operator+=(const bign&);
bign operator-(const bign &)const;
bign operator--();
bign operator--(int);
bign operator-=(const bign&);
bign operator*(const bign&)const;
bign operator*(const int num)const;
bign operator*=(const bign&);
bign operator/(const bign&)const;
bign operator/=(const bign&);
//四则扩展运算符重载
bign operator%(const bign&)const;
//剩下的函数
void dis(){if(sign==0)cout<<"-";
for(int i=0;i<len;i++)std::cout<<s[len-i-1];
std::cout<<std::endl;
}
};
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
bign::bign(){memset(s,0,sizeof(s));len=1;sign=1;}
bign::bign(const char *num){*this=num;}
bign::bign(int num){*this=num;}
string bign::to_str()const{
string res;
res="";//初始化
int i;
for(i=0;i<len;i++)
res=(char)(s[i]+'0')+res;
if(res=="")return "0";
if(sign!=1&&res!="")res='-'+res;
return res;
}
istream &operator>>(istream &in,bign&num){
string res;
in>>res;
num=res;
return in;
}
ostream &operator<<(ostream &out,bign&num){
out<<num.to_str();
return out;
}
bign bign::operator=(const char*num){
memset(s,0,sizeof(s));//s初始化
char tmp[MAX_L]="";
if(num[0]!='-')strcpy(tmp,num);
else {for(int i=1;i<strlen(num);i++)tmp[i-1]=num[i];}
len=strlen(tmp);sign=!(num[0]=='-');
for(int i=0;i<len;i++)
s[i]=tmp[len-i-1]-'0';
int i=len-1;
while(s[i]==0&&i>0){i--;len--;}
return *this;
}
bign bign::operator=(int num){
//也可以采用sprintf
int i=0;
if(num<0){sign=0;num=-1*num;}
else sign=1;
int a=num;int tmp;
while(a>0){tmp=a;a=a/10;s[i++]=tmp%10;}
len=i;
i=len-1;
while(s[i]==0&&i>0){i--;len--;}
return *this;
}
bign bign::operator=(const string num){
const char *tmp;
tmp=num.c_str();
*this=tmp;
return *this;
}
bool bign::operator>(const bign &obj)const{
if(sign^obj.sign)return (*this).sign;//不同符号
if(len!=obj.len)return sign?(len>obj.len):(!(len>obj.len));//相同符号不同长度
for(int i=len-1;i>=0;i--)
if(s[i]!=obj.s[i])
return sign?(s[i]>obj.s[i]):(!(s[i]>obj.s[i]));
return 0;
}
bool bign::operator<(const bign &obj)const{
return (obj>*this);
}
bool bign::operator>=(const bign &obj)const{
return !(*this<obj);
}
bool bign::operator<=(const bign &obj)const{
return ~(*this>obj);
}
bool bign::operator!=(const bign &obj)const{
return (*this>obj)||(*this<obj);
}
bool bign::operator==(const bign &obj)const{
return !(*this!=obj);
}
bign bign::operator+(const bign&num)const{
bign res;
res.len=0;
int i;
if(sign^num.sign){
bign tmp=sign?num:*this;//找出减数
tmp.sign=1;//加法变成减法
res=sign?*this-tmp:num-tmp;
}//两者不同符号
else{
int add=0;
for(i=0;add||i<(max(len,num.len));i++)
{
int t=s[i]+num.s[i]+add;
res.s[res.len++]=t%10;add=t/10;
}
res.sign=sign;
int i=res.len-1;
while(res.s[i]==0&&i>0){i--;res.len--;}
}//两者同号
return res;
}
bign bign::operator++(){
*this=*this+1;
return *this;
}
bign bign::operator++(int){
bign tmp=*this;
++(*this);
return tmp;
}
bign bign::operator+=(const bign&num){
*this=*this+num;
return *this;
}
bign bign::operator-(const bign&num)const{
bign a=*this;//被减数
bign b=num;//减数
bign res;res.len=0;
if(!sign&&!num.sign){
a.sign=1;b.sign=1;
res=b-a;
}//两数都是负数
else if(!num.sign){b.sign=1;res=a+b;}//减数是负数
else if(!sign){a.sign=1;res=bign(0)-(a+b);}//被减数是负数
else{
if(a<b){res=b-a;res.sign=0;}//被减数小
else{int add=0;
for(int i=0;i<a.len;i++)
{int t=a.s[i]-add;
if(i<b.len)t=t-b.s[i];
if(t>=0)add=0;
else{add=1;t=t+10;}//退位
res.s[res.len++]=t;
}
}//被减数大
}//两者都是正数
int i=res.len-1;
while(res.s[i]==0&&i>0){i--;res.len--;}
return res;
}
bign bign::operator--(){
*this=*this-1;
return *this;
}
bign bign::operator--(int){
bign tmp=*this;
--(*this);
return tmp;
}
bign bign::operator-=(const bign&num){
*this=*this-num;
return *this;
}
bign bign::operator*(const bign&num)const{
bign res;
res.len=len+num.len-1;
int i,j;
for(i=0;i<len;i++)
for(j=0;j<num.len;j++)
{
res.s[i+j]+=s[i]*num.s[j];
}
int add=0;
for(i=0;i<res.len;i++)
{int t=res.s[i]+add;res.s[i]=t%10;add=t/10;}
res.sign=!(sign^num.sign);
i=res.len-1;
while(res.s[i]==0&&i>0){i--;res.len--;}
return res;
}
bign bign::operator*=(const bign&num){
*this=*this*num;
return *this;
}
bign bign::operator*(const int num)const{
bign x=num;
return *this*x;
}
bign bign::operator/(const bign&num)const{
bign res;
res.len=len-num.len+1;
if(res.len<0){res.len=1;return res;}//被除数小
bign a=*this;//被除数
bign b=num;//除数
a.sign=b.sign=1;
int i;
bign tmp=0;
for(i=len-1;i>=0;i--)
{tmp=tmp*10;
tmp.s[0]=s[i];//每次循环就是一次移位
while(tmp>=b){tmp-=b;res.s[i]++;}
}
res.sign=!(sign^num.sign);
i=res.len-1;
while(res.s[i]==0&&i>0){i--;res.len--;}
return res;
}
bign bign::operator/=(const bign&num){
*this=*this/num;
return *this;
}
bign bign::operator%(const bign&num)const{
bign res=*this/num;
res=*this-res*num;
return res;
}