前言
一直在用板子,然后考虑到有些细节还不是很清楚,就整理一下吧。然后没有按板子来写,但是思想基本一致,因为我的板子是每四位合并成一位,也就是将大数看做一个 10000 10000 10000进制数
构造和输出
大数一位位地输入比较慢,因此一般采用字符串输入,然后将字符串转化为大数
注意需要从后向前存,运算时从前向后运算,输出时从后向前输出
const int maxn=1005;
struct BigInt{
int a[maxn];
int len;
BigInt(){ len=1; memset(a,0,sizeof a); }
BigInt(char *s){
len=strlen(s);
int cnt=0;
for(int i=len-1;i>=0;i--) a[cnt++]=s[i]-'0';
}
BigInt(string s){
len=s.size();
int cnt=0;
for(int i=len-1;i>=0;i--) a[cnt++]=s[i]-'0';
}
BigInt& operator = (const BigInt &T){ //重载赋值运算符,大数之间进行赋值运算
len=T.len;
memset(a,0,sizeof(a));
for(int i=0;i<len;i++)
a[i]=T.a[i];
return *this;
}
void println(){
for(int i=len-1;i>=0;i--) printf("%d",a[i]);
puts("");
}
void print(){
for(int i=len-1;i>=0;i--) printf("%d",a[i]);
}
};
逻辑比较
>
bool operator > (const BigInt &T) const {
if(len>T.len) return 1;
if(len<T.len) return 0;
int cur=len-1;
while(a[cur]==T.a[cur] && cur>=0) cur--;
if(cur>=0 && a[cur]>T.a[cur]) return 1;
else return 0;
}
<
bool operator < (const BigInt &T) const {
if(len<T.len) return 1;
if(len>T.len) return 0;
int cur=len-1;
while(a[cur]==T.a[cur] && cur>=0) cur--;
if(cur>=0 && a[cur]<T.a[cur]) return 1;
else return 0;
}
==
bool operator == (const BigInt &T) const {
if(len!=T.len) return 0;
for(int i=len-1;i>=0;i--)
if(a[cur]!=T.a[cur]) return 0;
return 1;
}
四则运算
大数加法
实际上就是对每一位相加并处理进位即可
BigInt operator + (const BigInt &T) const {
BigInt ret=T;
int maxlen=len>T.len?len:T.len; //取长度最长的那个
for(int i=0;i<maxlen;i++){
ret.a[i]+=a[i];
if(ret.a[i]>=10){
ret.a[i+1]++;
ret.a[i]-=10;
}
}
ret.len=ret.a[maxlen]>0?maxlen+1:maxlen;
return ret;
}
大数减法
BigInt operator - (const BigInt &T) const {
BigInt t1,t2;
bool flag;
if(*this>T){ //取得最大数并标记首位是否为负
t1=*this,t2=T;
flag=0;
}else{
t1=T,t2=*this;
flag=1;
}
int maxlen=t1.len;
for(int i=0;i<maxlen;i++){
if(t1.a[i]<t2.a[i]){ //需要向前借位
int j=i+1;
while(t1.a[i]==0) j++;
t1.a[j--]--;
while(j>i) t1.a[j--]=9;
t1.a[i]+=10-t2.a[i];
}else t1.a[i]-=t2.a[i];
}
while(t1.a[maxlen-1]==0 && t1.len>1){ //看看从最高位开始是否被借位变为0
t1.len--;
maxlen--;
}
if(flag) t1.a[maxlen-1]=-t1.a[maxlen-1]; //处理首位的正负
return t1;
}
大数乘法
BigInt operator * (const BigInt &T) const {
BigInt ret;
int i,j,temp1,temp2,up;
for(i=0;i<len;i++){
up=0;
for(j=0;j<T.len;j++){
temp1=a[i]*T.a[j]+ret.a[i+j]+up;
if(temp1>=10){
temp2=temp1-temp1/10*10;
up=temp1/10;
ret.a[i+j]=temp2;
}else{
up=0;
ret.a[i+j]=temp1;
}
}
if(up) ret.a[i+j]=up; //向最高位的进位是否存在
}
ret.len=len+T.len;
while(ret.a[ret.len-1]==0 && ret.len>1) ret.len--; //处理前导0
return ret;
}
大数除法
BigInt operator / (const int &b) const {
BigInt ret;
int down=0;
for(int i=len-1;i>=0;i--){
ret.a[i]=(a[i]+down*10)/b;
down=a[i]+down*10-ret.a[i]*b;
}
ret.len=len;
while(ret.a[ret.len-1]==0 && ret.len>1) ret.len--;
return ret;
}
其他操作
大数取模
以
43
43%3
43为例:
然后我们可以发现实际上需要的是对每一位依次取模,并加上来自高位的余数乘以十
int operator % (const int &b) const {
int ret=0;
for(int i=len-1;i>=0;i--)
ret=(ret*10+a[i])%b;
return ret;
}
大数求幂
BigInt pow(int n){ //传入的n非负
BigInt x=*this,ret("1");
while(n) {
if(n&1) ret=ret*x;
x=x*x;
n>>=1;
}
return ret;
}