文章目录
Update8.12:更改了一些错误的地方
前置芝士-运算符重载
例子
看下边的代码:
#inclue<iostream>
using namespace std;
int main(){
int a,b;
cin>>a>>b;
cout<<a+b;
}
cin>>a>>b
在这里是指输入两个数 a , b a,b a,b,就有人会问了,>>
不是右移吗?怎么用来输入变量了?其实这就是一个简单的运算符重载。
方法
那么我们改怎么重载呢?
类型 operator 符号(参数) const {
内容(记得带返回值)
}
其中const
是要在结构体里面定义的时候才加。
可以重载的符号有:
new delete new[] delete[]
+ - * / % ^ & & | ~
! = < > += -= *= /= %=
^= &= |= << >> >>= <<=
== != <= >= && || ++
-- , ->* -> () []
其中[]
指下标,
可以有两个参数,也可以有一个参数的有:
+ - * &
当然,重载流输流输出有不一样的格式,这是友元函数:
friend istream & operator >> (istream &,bigint &x){
...
return cin;
}
friend ostream & operator <<(ostream &,bigint x){
...
return cout;
}
高精度运算
存储
有些时候进行运算的时候,数字会很大,导致int_128
都装不下,不如自己动手,丰衣足食,自己定义一种变量,满足进行很大的数字的运算。这里叫bigint
那么,bigint
里面要有什么东西呢?我们先看一下short
是怎么存贮的:主要是int有32位画不下
我们就可以定义一个数组,数组的每一位,代表每一个数。还有两个变量,一个代表长度,一个代表正负,就是这样:
struct bigint{
int len,flag;//flag 1 fu 0 zheng
int a[maxn];
}
输入输出&&运算原理
然后考虑怎么运算,其实很简单,就像小学生一样做竖式运算就可以了,为了方便进行运算,令 a 1 a_1 a1为个位, a 2 a_2 a2为十位, a 3 a_3 a3为百位,以此类推即可。
然后考虑怎么输入,我们发现,输入的是一个很大的数字,不能直接用cin
,为了一次性读入,我们读入一个字符串 s s s,不难得到 a i = s l e n − i a_i=s_{len-i} ai=slen−i,最后删去前导零,比如说 0001 0001 0001要写成 1 1 1
输出只要倒着输出就可以了。一个for循环搞定。记得注意符号。
奉上输入输出重载:
friend istream & operator >> (istream &,bigint &x){
char s[maxn]; cin>>s;
x.len=strlen(s);
if(s[0]=='-') x.flag=1;
memset(x.a,0,sizeof(x.a));
if(x.flag)
for(register int i=1;i<x.len;i++)
x.a[i]=s[x.len-i]^48;
else for(register int i=1;i<=x.len;i++)
x.a[i]=s[x.len-i]^48;
for(;x.len>1;x.len--)
if(x.a[x.len]!=0)
break;//删去前导零
return cin;
}
friend ostream & operator <<(ostream & ,bigint x){
if(x.flag) printf("-");
int flag=0;
for(register int i=x.len;i>=1;i--){
if(x.a[i]>0) flag=1;
if(flag)
printf("%d",x.a[i]);
}
if(!flag) putchar('0');
return cout;
}
加减
加减只要按照竖式法从低到高加就可以了,还要注意进位,算法复杂度 Θ ( n ) \Theta(n) Θ(n)
注意正负就可以了。(初中老师应该讲过有理数的加减的吧)
乘除
乘法依旧是竖式计算,不过正负的处理更加简单。
注意 a i × b j a_i\times b_j ai×bj的结果应该储存在 a n s i + j − ‘ ans_{i+j-`} ansi+j−‘中,注意ans.len=a.len+b.len-1
或者ans.len=a.len+b.len
除法也可以用竖式解决,这里暂时不涉及。
代码
最后献上代码。据说很多人喜欢这个
struct bigint{
int len,flag;//flag 1 fu 0 zheng
int a[maxn];
bigint (*intit)(int);
void (*check)(bigint);
friend istream & operator >> (istream &,bigint &x){
char s[maxn]; cin>>s;
x.len=strlen(s);
if(s[0]=='-') x.flag=1;
memset(x.a,0,sizeof(x.a));
if(x.flag)
for(register int i=1;i<x.len;i++)
x.a[i]=s[x.len-i]^48;
else for(register int i=1;i<=x.len;i++)
x.a[i]=s[x.len-i]^48;
for(;x.len>1;x.len--)
if(x.a[x.len]!=0)
break;//ɾȥǰµ¼Áã
return cin;
}
friend ostream & operator <<(ostream & ,bigint x){
if(x.flag) printf("-");
int flag=0;
for(register int i=x.len;i>=1;i--){
if(x.a[i]>0) flag=1;
if(flag)
printf("%d",x.a[i]);
}
if(!flag) putchar('0');
return cout;
}
bool operator > (const bigint &x)const{
if(!x.flag&&!this->flag){
if(this->len > x.len ) return true;
if(this->len < x.len ) return false;
for(int i=x.len;i>=1;i--)
if( this->a[i] > x.a[i] ) return true;
else if( this->a[i] < x.a[i] ) return false;
}
if(this->flag&&!x.flag) return false;
if(!this->flag&&x.flag) return true;
if(this->len < x.len ) return true;
if(this->len > x.len ) return false;
for(int i=x.len;i>=1;i--)
if( this->a[i] < x.a[i] ) return true;
else if( this->a[i] > x.a[i] ) return false;
return false;
}
bool operator == (const bigint &x)const{
if(x.flag!=this->flag) return 0;
for(int i=1;i<=max(x.len,this->len);i++)
if(x.a[i]!=this->a[i])
return 0;
return 1;
}
bool operator < (const bigint &x) const {
return !(*this>=x); }
bool operator <= (const bigint &x) const {
return !(*this>x); }
bool operator >= (const bigint &x) const {
return *this>x || *this==x;}
bigint operator +(const bigint &x) const {
bigint ans=(bigint){
0,0,{
}};
int jw=0;
if(this->flag==x.flag){
ans.flag=x.flag;
ans.len=max(this->len,x.len);
for(int i=1;i<=ans.len;i++)
if(this->a[i]+x.a[i]+jw>=10){
ans.a[i]=(this->a[i]+x.a[i]+jw)-10;
jw=1;
}
else{
ans.a[i]=(this->a[i]+x.a[i]+jw);
jw=0;
}
if(jw==1){
ans.len++; ans.a[ans.len]=1; }
return ans;
}
bigint thi;
int flag,tw;
if(this->flag==1&&x.flag==0){
memset(thi.a,0,sizeof(thi.a));
for(int i=1;i<=x.len;i++)
thi.a[i]=this->a[i];
thi.flag=0;
thi.len=this->len;
if(thi>x){
ans.flag=1;
for(int i=1;i<=thi.len;i++)
if(thi.a[i]-tw-x.a[i]<0){
ans.a[i]=thi.a[i]-tw-x.a[i]+10;
tw=1;
}
else{
ans.a[i]=thi.a[i]-tw-x.a[i];
tw=0;
}
ans.len=thi.len;
}
else{
ans.flag=0;
for(int i=1;i<=x.len;i++)
if(x.a[i]-tw-thi.a[i]<0){
ans.a[i]=x.a[i]-tw-thi.a[i]+10;
tw=1;
}
else{
ans.a[i]=x.a[i]-tw-thi.a[i];
tw=0;
}
ans.len=x.len;
}
}
if(this->flag==0&&x.flag==1){
memset(thi.a,0,sizeof(thi));
for(int i=1;i<=x.len;i++)
thi.a[i]=x.a[i];
thi.flag=0; thi.len=x.len;
if(*this>=thi){
ans.flag=0; ans.len=this->len;
for(int i=1;i<=ans.len;i++)
if(this->a[i]-tw-thi.a[i]<0){
ans.a[i]=this->a[i]-tw-thi.a[i]+10;
tw=1;
}
else{
ans.a[i]=this->a[i]-tw-thi.a[i];
tw=0;
}
}
else{
ans.flag=1; ans.len=thi.len;
for(int i=1;i<=ans.len;i++)
if(thi.a[i]-tw-this->a[i]<0){
ans.a[i]=thi.a[i]-tw-this->a[i]+10;
tw=1;
}
else{
ans.a[i]=thi.a[i]-tw-this->a[i];
tw=0;
}
}
}
while(ans.len>1&&ans.a[ans.len]==1) ans.len--;
return ans;
}
bigint operator -(const bigint &x) const {
bigint thi;
memset(thi.a,0,sizeof(thi.a));
thi.len=x.len;
for(int i=1;i<=x.len;i++)
thi.a[i]=x.a[i];
thi.flag=!x.flag;
return *this+thi;
}
bigint operator *(bigint &x){
bigint ans=(bigint){
0,0,{
0}};
for(register int i=1;i<=x.len;i++)
for(register int j=1;j<=this->len;j++){
ans.a[i+j-1]+=this->a[j]*x.a[i];
ans.a[i+j]+=ans.a[i+j-1]/10;
ans.a[i+j-1]%=10;
}
ans.len=this->len+x.len+1;
ans.flag=(this->flag)^(x.flag);
while(ans.a[ans.len]==0&&ans.len>1) ans.len--;
return ans;
}
};
bigint intit(int x){
bigint ans=(bigint){
0,0,{
0}};
if(x<0){
x=-x;
ans.flag=1;
}
if(x==0){
ans.len=1;
return ans;
}
while(x>0){
ans.a[++ans.len]=x%10;
x/=10;
}
return ans;
}
记得定义maxn
的大小哦~~~(maxn
是位数)
这里重载了 >> << + - * > < >= <= ==
bigint init(int)
是把一个int类型的数转化成bigint类型。
完结撒花