背景:
C++中有时我们会遇到(unsigned)long long也表示不了的大整数,这个时候我们常常会用高精度
为了简化使用过程以及模板化,我们不妨用struct或class来定义
详解:
框架:
template<int SIZE>//用来限制最大表示位数
class bign(){
private://在class外不能调用
int a[SIZE],len;//高精度整数,用数组表示
public:
//一系列运算函数
}
输入输出:
bign(){len=1;memset(a,0,sizeof(a));}//初始化
void in(){
char s[SIZE];
scanf("%s",s);
len=strlen(s);
for(int i=0,j=len-1;i<len;i++,j--) a[i]=s[j]-48;
while(len>1&&a[len-1]==0) len--;//应对输入含前导0
}
void out(bool Entr=true){//默认输出换行
for(int i=len-1;i>=0;i--) putchar(a[i]+'0');
if(Entr) putchar('\n');
}
赋值:
这部分主要是模拟实现,就不加注释了。相当于小学算数,自己思考一下
void operator = (char *s){
len=strlen(s);
for(int i=0,j=len-1;i<len;i++,j--) a[i]=s[j]-48;
while(len>1&&a[len-1]==0) len--;
}
void operator = (int x){
len=0;if(x==0) len=1,a[0]=0;
while(x>0) a[len++]=x%10,x/=10;
}
void operator = (long long x){
len=0;if(x==0) len=1,a[0]=0;
while(x>0) a[len++]=x%10,x/=10;
}
大小比较:
friend bool operator < (bign a,bign b){
if(a.len!=b.len) return a.len<b.len;
for(int i=a.len-1;i>=0;i--)
if(a.a[i]!=b.a[i]) return a.a[i]<b.a[i];
return false;//表示a,b相等
}
friend bool operator > (bign a,bign b){
return b<a;
}
friend bool operator <= (bign a,bign b){
return !(a>b);
}
friend bool operator >= (bign a,bign b){
return !(a<b);
}
friend bool operator == (bign a,bign b){
return !(a>b&&b<a);
}
friend bool operator != (bign a,bign b){
return a<b||b<a;
}
加减乘除运算:
friend bign operator + (bign a,bign b){
bign c;
int lenth=max(a.len,b.len)+1;
for(int i=0;i<lenth;i++) c.a[i]=a.a[i]+b.a[i];
for(int i=0;i<lenth;i++){
if(c.a[i]>9) c.a[i]-=10,c.a[i+1]++;
}
while(lenth>1&&c.a[lenth-1]==0) lenth--;
c.len=lenth;
return c;
}
friend bign operator - (bign a,bign b){//求a-b的绝对值
bign c;
if(a<b) swap(a,b);
int len=a.len;
for(int i=0;i<len;i++)
c.a[i]=a.a[i]-b.a[i];
for(int i=0;i<len;i++)
if(c.a[i]<0) c.a[i+1]--, c.a[i]+=10;
while(len>1&&c.a[len-1]==0) len--;
c.len=len;
return c;
}
friend bign operator * (bign a,bign b){
bign ans;
int len=a.len+b.len;
for(int i=0;i<a.len;i++)
for(int j=0;j<b.len;j++)
ans.a[i+j]+=a.a[i]*b.a[j];//这里要思考一下
for(int i=0;i<len;i++)
if(ans.a[i]>9) ans.a[i+1]+=ans.a[i]/10,ans.a[i]%=10;
while(len>1&&ans.a[len-1]==0) len--;
ans.len=len;
return ans;
}
friend bign operator * (bign a,int x){//防溢出,x<=200,000,000
bign ans;
int len=a.len+20;
for(int i=0;i<len;i++) ans.a[i]=a.a[i]*x;
for(int i=0;i<len;i++)
if(ans.a[i]>9) ans.a[i+1]+=ans.a[i]/10,ans.a[i]%=10;
while(ans.a[len-1]==0&&len>1) len--;
ans.len=len;
return ans;
}
friend bign operator / (bign a,int b){//防溢出
bign c;
int d=0,len=a.len;
for(int i=len-1;i>=0;i--)
d=d*10+a.a[i],c.a[i]=d/b,d=d%b;
while(len>1&&c.a[len-1]==0) len--;
c.len=len;
return c;
}
friend bign operator / (bign a,bign b){
bign c,d;
int len=a.len;
for(int i=len-1;i>=0;i--){
d=d*10;
d.a[0]=a.a[i];
while(d>=b) c.a[i]++, d=d-b;//这里效率不是很高
}
while(len>1&&c.a[len-1]==0) len--;
c.len=len;
return c;
}
取模:
friend int operator % (bign a,int b){//注意返回值为int
int d=0,len=a.len;
for(int i=len-1;i>=0;i--)
d=d*10+a.a[i],d=d%b;
return d;
}
friend bign operator % (bign a,bign b){
bign d;
int len=a.len;
for(int i=len-1;i>=0;i--){
d=d*10;
d.a[0]=a.a[i];
while(d>=b) d=d-b;//同理,效率不够高
}
while(len>1&&d.a[len-1]==0) len--;
d.len=len;
return d;
}
部分扩展功能:
friend bign gcd(bign a,bign b){//求最大公约数
bign zero;
zero=0;
return b==zero?a:gcd(b,a%b);
}
friend bign pow_mod(int a,int n,bign m){//求a^n mod m (m为高精度数)
bign ret,X;
if(n==0){
ret=1;return ret;
}
X=pow_mod(a,n/2,m);
ret=(X*X)%m;
if(n%2) ret=(ret*a)%m;
return ret;
}
完整代码:
template<int SIZE>
class bign{
private:
int a[SIZE],len;
public:
bign(){len=1;memset(a,0,sizeof(a));}
void in(){
char s[SIZE];
scanf("%s",s);
len=strlen(s);
for(int i=0,j=len-1;i<len;i++,j--) a[i]=s[j]-48;
while(len>1&&a[len-1]==0) len--;
}
void out(bool Entr=true){
for(int i=len-1;i>=0;i--) putchar(a[i]+'0');
if(Entr) putchar('\n');
}
void operator = (char *s){
len=strlen(s);
for(int i=0,j=len-1;i<len;i++,j--) a[i]=s[j]-48;
while(len>1&&a[len-1]==0) len--;
}
void operator = (int x){
len=0;if(x==0) len=1,a[0]=0;
while(x>0) a[len++]=x%10,x/=10;
}
void operator = (long long x){
len=0;if(x==0) len=1,a[0]=0;
while(x>0) a[len++]=x%10,x/=10;
}
friend bool operator < (bign a,bign b){
if(a.len!=b.len) return a.len<b.len;
for(int i=a.len-1;i>=0;i--)
if(a.a[i]!=b.a[i]) return a.a[i]<b.a[i];
return false;
}
friend bool operator > (bign a,bign b){
return b<a;
}
friend bool operator <= (bign a,bign b){
return !(a>b);
}
friend bool operator >= (bign a,bign b){
return !(a<b);
}
friend bool operator == (bign a,bign b){
return !(a>b&&b<a);
}
friend bool operator != (bign a,bign b){
return a<b||b<a;
}
friend bign operator + (bign a,bign b){
bign c;
int lenth=max(a.len,b.len)+1;
for(int i=0;i<lenth;i++) c.a[i]=a.a[i]+b.a[i];
for(int i=0;i<lenth;i++){
if(c.a[i]>9) c.a[i]-=10,c.a[i+1]++;
}
while(lenth>1&&c.a[lenth-1]==0) lenth--;
c.len=lenth;
return c;
}
friend bign operator - (bign a,bign b){
bign c;
if(a<b) std::swap(a,b);
int len=a.len;
for(int i=0;i<len;i++)
c.a[i]=a.a[i]-b.a[i];
for(int i=0;i<len;i++)
if(c.a[i]<0) c.a[i+1]--, c.a[i]+=10;
while(len>1&&c.a[len-1]==0) len--;
c.len=len;
return c;
}
friend bign operator * (bign a,bign b){
bign ans;
int len=a.len+b.len;
for(int i=0;i<a.len;i++)
for(int j=0;j<b.len;j++)
ans.a[i+j]+=a.a[i]*b.a[j];
for(int i=0;i<len;i++)
if(ans.a[i]>9) ans.a[i+1]+=ans.a[i]/10,ans.a[i]%=10;
while(len>1&&ans.a[len-1]==0) len--;
ans.len=len;
return ans;
}
friend bign operator * (bign a,int x){
bign ans;
int len=a.len+20;
for(int i=0;i<len;i++) ans.a[i]=a.a[i]*x;
for(int i=0;i<len;i++)
if(ans.a[i]>9) ans.a[i+1]+=ans.a[i]/10,ans.a[i]%=10;
while(ans.a[len-1]==0&&len>1) len--;
ans.len=len;
return ans;
}
friend bign operator / (bign a,int b){
bign c;
int d=0,len=a.len;
for(int i=len-1;i>=0;i--)
d=d*10+a.a[i],c.a[i]=d/b,d=d%b;
while(len>1&&c.a[len-1]==0) len--;
c.len=len;
return c;
}
friend bign operator / (bign a,bign b){
bign c,d;
int len=a.len;
for(int i=len-1;i>=0;i--){
d=d*10;
d.a[0]=a.a[i];
while(d>=b) c.a[i]++, d=d-b;
}
while(len>1&&c.a[len-1]==0) len--;
c.len=len;
return c;
}
friend int operator % (bign a,int b){
int d=0,len=a.len;
for(int i=len-1;i>=0;i--)
d=d*10+a.a[i],d=d%b;
return d;
}
friend bign operator % (bign a,bign b){
bign d;
int len=a.len;
for(int i=len-1;i>=0;i--){
d=d*10;
d.a[0]=a.a[i];
while(d>=b) d=d-b;
}
while(len>1&&d.a[len-1]==0) len--;
d.len=len;
return d;
}
friend bign gcd(bign a,bign b){
bign zero;
zero=0;
return b==zero?a:gcd(b,a%b);
}
friend bign pow_mod(int a,int n,bign m){
bign ret,X;
if(n==0){
ret=1;return ret;
}
X=pow_mod(a,n/2,m);
ret=(X*X)%m;
if(n%2) ret=(ret*a)%m;
return ret;
}
};