過載“+-*/”實現高精度運算
阿新 • • 發佈:2019-02-05
在只進行加法和減法時,我們可以壓八位來加快速度,當有乘法時,壓八位會爆int所以我們壓四位。 高精度除法壓位比較難寫,所以我們不選擇壓位。在程式的前端宣告一個變數P來記錄壓位的位數,M記錄壓N位時對應的最小的數,即可使程式更容易除錯。
const int M=100000000,
P=8;
//輸出可以這樣寫
printf("%*d",P,n[i]);
加減,壓八位,輸出補零
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; const int M=100000000, P=8; //壓位 struct bignum { int n[5000],l; //n陣列存放每個結構體中的"大數",l記錄長度。 bignum(){l=1,memset(n,0,sizeof(n));} //----------------------------------------------- void init() //輸入過程 { string s; cin>>s; int now=0,ct=0,c1=1; //now記錄當前是n陣列的第幾位,ct記錄已經讀入多少字元了,滿八進一,c1是輔助變數,因為我們是倒著讀入,所以每次要乘10 for(int i=s.length()-1;i>=0;i--) //從s的長度-1開始 { n[now]+=(s[i]-'0')*c1; c1*=10; ct++; if(ct==P&&i!=0) // 如果i=0了就沒有必要now++; { now++; ct=0; c1=1; } } l=now+1; //l的長度為now+1; } void print() { printf("%d",n[l-1]); for(int i=l-2;i>=0;i--) printf("%0*d",P,n[i]); //補零輸出 printf("\n"); } //----------------------------------------------- bignum operator + (bignum x) const //過載加號 { bignum t=*this; if(x.l>t.l)t.l=x.l; for(int i=0;i<t.l;i++) { t.n[i]+=x.n[i]; if(t.n[i]>=M) { t.n[i+1]+=t.n[i]/M; t.n[i]%=M; } } return t; // 注意:將t的值返回 } //------------------------------------------------ bool operator < (bignum x) const //過載小於號 { bignum t=*this; if(t.l!=x.l)return t.l<x.l; for(int i=t.l-1;i>=0;i--) { if(t.n[i]!=x.n[i]) return t.n[i]<x.n[i]; } return 0; } bignum operator -(bignum x) const //過載減號 { bignum t=*this; if(t<x){printf("-");swap(t,x);} int jie =0; for(int i=0;i<t.l;i++) { t.n[i]-=x.n[i]; while(t.n[i]<0) { t.n[i]+=M; jie++; } t.n[i+1]-=jie; jie=0; } while(!t.n[t.l-1] && t.l>1)t.l--; // 相減後有可能出現前面有0的情況,所以t.l--; return t; } //---------------------------------------------- }a,b,c; int main() { a.init(); //讀入字串a和b b.init(); c=a+b; c.print(); c=a-b; c.print(); c=a*b; c.print(); return 0; }
加減乘,壓四位,輸出補零
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; const int M=10000, P=4; //壓位 struct bignum { int n[5000],l; //n陣列存放每個結構體中的"大數",l記錄長度。 bignum(){l=1,memset(n,0,sizeof(n));} //----------------------------------------------- void init() //輸入過程 { string s; cin>>s; int now=0,ct=0,c1=1; //now記錄當前是n陣列的第幾位,ct記錄已經讀入多少字元了,滿八進一,c1是輔助變數,因為我們是倒著讀入,所以每次要乘10 for(int i=s.length()-1;i>=0;i--) //從s的長度-1開始 { n[now]+=(s[i]-'0')*c1; c1*=10; ct++; if(ct==P&&i!=0) // 如果i=0了就沒有必要now++; { now++; ct=0; c1=1; } } l=now+1; //l的長度為now+1; } void print() { printf("%d",n[l-1]); for(int i=l-2;i>=0;i--) printf("%0*d",P,n[i]); //補零輸出 printf("\n"); } //----------------------------------------------- bignum operator + (bignum x) const //過載加號 { bignum t=*this; if(x.l>t.l)t.l=x.l; for(int i=0;i<t.l;i++) { t.n[i]+=x.n[i]; if(t.n[i]>=M) { t.n[i+1]+=t.n[i]/M; t.n[i]%=M; } } return t; // 注意:將t的值返回 } //------------------------------------------------ bool operator < (bignum x) const //過載小於號 { bignum t=*this; if(t.l!=x.l)return t.l<x.l; for(int i=t.l-1;i>=0;i--) { if(t.n[i]!=x.n[i]) return t.n[i]<x.n[i]; } return 0; } bignum operator -(bignum x) const //過載減號 { bignum t=*this; if(t<x){printf("-");swap(t,x);} int jie =0; for(int i=0;i<t.l;i++) { t.n[i]-=x.n[i]; while(t.n[i]<0) { t.n[i]+=M; jie++; } t.n[i+1]-=jie; jie=0; } while(!t.n[t.l-1] && t.l>1)t.l--; // 相減後有可能出現前面有0的情況,所以t.l--; return t; } //------------------------------------------------ bignum operator *(bignum x) const //過載乘號 { bignum t=*this,tep; tep.l=t.l+x.l-1; for(int i=0;i<t.l;i++) for(int j=0;j<x.l;j++) { tep.n[i+j]+=t.n[i]*x.n[j]; if(tep.n[i+j]>=M) { tep.n[i+j+1]+=tep.n[i+j]/M; tep.n[i+j]%=M; } } while(tep.n[tep.l]) { tep.n[tep.l+1]+=tep.n[tep.l]/M; tep.n[tep.l++]%=M; } return tep; } //----------------------------------------- }a,b,c; int main() { a.init(); //讀入字串a和b b.init(); c=a+b; c.print(); c=a-b; c.print(); c=a*b; c.print(); return 0; }
加減乘除,不壓位
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; const int M=10, P=1; //壓位 struct bignum { int n[5000],l; //n陣列存放每個結構體中的"大數",l記錄長度。 bignum(){l=1,memset(n,0,sizeof(n));} //----------------------------------------------- void init() //輸入過程 { string s; cin>>s; int now=0,ct=0,c1=1; //now記錄當前是n陣列的第幾位,ct記錄已經讀入多少字元了,滿八進一,c1是輔助變數,因為我們是倒著讀入,所以每次要乘10 for(int i=s.length()-1;i>=0;i--) //從s的長度-1開始 { n[now]+=(s[i]-'0')*c1; c1*=10; ct++; if(ct==P&&i!=0) // 如果i=0了就沒有必要now++; { now++; ct=0; c1=1; } } l=now+1; //l的長度為now+1; } void print() { printf("%d",n[l-1]); for(int i=l-2;i>=0;i--) printf("%0*d",P,n[i]); //補零輸出 printf("\n"); } //----------------------------------------------- bignum operator + (bignum x) const //過載加號 { bignum t=*this; if(x.l>t.l)t.l=x.l; for(int i=0;i<t.l;i++) { t.n[i]+=x.n[i]; if(t.n[i]>=M) { t.n[i+1]+=t.n[i]/M; t.n[i]%=M; } } return t; // 注意:將t的值返回 } //------------------------------------------------ bool operator < (bignum x) const //過載小於號 { bignum t=*this; if(t.l!=x.l)return t.l<x.l; for(int i=t.l-1;i>=0;i--) { if(t.n[i]!=x.n[i]) return t.n[i]<x.n[i]; } return 0; } bignum operator -(bignum x) const //過載減號 { bignum t=*this; if(t<x){printf("-");swap(t,x);} int jie =0; for(int i=0;i<t.l;i++) { t.n[i]-=x.n[i]; while(t.n[i]<0) { t.n[i]+=M; jie++; } t.n[i+1]-=jie; jie=0; } while(!t.n[t.l-1] && t.l>1)t.l--; // 相減後有可能出現前面有0的情況,所以t.l--; return t; } //------------------------------------------------ bignum operator *(bignum x) const //過載乘號 { bignum t=*this,tep; tep.l=t.l+x.l-1; for(int i=0;i<t.l;i++) for(int j=0;j<x.l;j++) { tep.n[i+j]+=t.n[i]*x.n[j]; if(tep.n[i+j]>=M) { tep.n[i+j+1]+=tep.n[i+j]/M; tep.n[i+j]%=M; } } while(tep.n[tep.l]) { tep.n[tep.l+1]+=tep.n[tep.l]/M; tep.n[tep.l++]%=M; } return tep; } //----------------------------------------- void Add(int x){if(x||l)n[l++]=x;} //除法 void Re(){reverse(n,n+l);} //高精度除以高精度 bignum operator /(const bignum &x)const { bignum t=*this,r,y; y.l=0,r.l=t.l; for(int i=t.l-1;i>=0;--i) { y.Add(t.n[i]); y.Re(); while(!(y<x))y=y-x,r.n[i]++; while(!y.n[y.l-1] && y.l>=1)--y.l; y.Re(); } while(!r.n[r.l-1] && r.l>1)--r.l; return r; }bignum operator /(const int &x)const //高精度除以單精度 { bignum t=*this,r; r.l=t.l; int tmp=0; for(int i=t.l-1;i>=0;--i) { tmp+=t.n[i]; if(tmp>=x) r.n[i]+=tmp/x,tmp%=x; tmp*=M; } while(!r.n[r.l-1] && r.l>1)--r.l; return r; } }a,b,c; int main() { a.init(); //讀入字串a和b b.init(); c=a+b; c.print(); c=a-b; c.print(); c=a*b; c.print(); c=a/b; c.print(); return 0; }
最後剽竊一個功能更豐富的- -
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int M=10,P=1;
struct BigNum
{
int n[5000],l,Y;
BigNum(){l=1,memset(n,0,sizeof(n));}
//----------------------------------
void init()
{
string s;
cin>>s;
int now=0,ct=0,c1=1;
for(int i=s.length()-1;i>=0;i--)
{
n[now]+=(s[i]-'0')*c1;
c1*=10;
ct++;
if(ct==P&&i!=0)
{
now++;
c1=1;
ct=0;
}
}
l=now+1;
}
//-----------------------------------
void print()
{
printf("%d",n[l-1]);
for(int i=l-2;i>=0;i--)
printf("%0*d",P,n[i]);
printf("\n");
}
//------------------------------------
BigNum operator +(BigNum x)const
{
BigNum t=*this;
if(x.l>t.l)t.l=x.l;
for(int i=0;i<t.l;i++)
{
t.n[i]+=x.n[i];
if(t.n[i]>=M)
{
t.n[i+1]+=t.n[i]/M;
t.n[i]%=M;
}
}
while(t.n[t.l])
{
t.n[t.l+1]+=t.n[t.l]/M;
t.n[t.l++]%=M;
}
return t;
}
//--------------------------------------
bool operator < (BigNum x) const
{
BigNum t=*this;
if(t.l!=x.l)return t.l<x.l;
for(int i=t.l-1;i>=0;i--)
{
if(t.n[i]!=x.n[i])return t.n[i]<x.n[i];
}
return 0;
}
BigNum operator -(BigNum x)const
{
BigNum t=*this;
if(t<x){printf("-");swap(t,x);}
for(int i=0;i<t.l;i++)
{
t.n[i]-=x.n[i];
if(t.n[i]<0)
{
t.n[i]+=M;
--t.n[i+1];
}
}
while(!t.n[t.l-1]&&t.l>1)t.l--;
return t;
}
//--------------------------------------------
BigNum operator * (BigNum x) const
{
BigNum c,t=*this;
c.l=t.l+x.l-1;
for(int i=0;i<t.l;i++)
for(int j=0;j<x.l;j++)
{
c.n[i+j]+=t.n[i]*x.n[j];
if(c.n[i+j]>=M)
{
c.n[i+j+1]+=c.n[i+j]/M;
c.n[i+j]%=M;
}
}
while(c.n[c.l])
{
c.n[c.l+1]+=c.n[c.l]/M;
c.n[c.l++]%=M;
}
return c;
}
BigNum operator * (int x) const
{
BigNum t=*this,c;
c.l=t.l;
for(int i=0;i<t.l;i++)
{
c.n[i]+=t.n[i]*x;
if(c.n[i]>=M)
{
c.n[i+1]+=c.n[i]/M;
c.n[i]%=M;
}
}
while(c.n[c.l])
{
c.n[c.l+1]+=c.n[c.l]/M;
c.n[c.l++]%=M;
}
return c;
}
//--------------------------------------------
void Add(int x){if(x||l)n[l++]=x;}
void Re(){reverse(n,n+l);}
BigNum operator /(const BigNum &x)const
{
BigNum t=*this,r,y;
y.l=0,r.l=t.l;
for(int i=t.l-1;i>=0;--i)
{
y.Add(t.n[i]);
y.Re();
while(!(y<x))y=y-x,r.n[i]++;
while(!y.n[y.l-1] && y.l>1)--y.l;
y.Re();
}
while(!r.n[r.l-1] && r.l>1)--r.l;
return r;
}
BigNum operator /(const int &x)const
{
BigNum t=*this,r;
r.l=t.l;
int tmp=0;
for(int i=t.l-1;i>=0;--i)
{
tmp+=t.n[i];
if(tmp>=x)
r.n[i]+=tmp/x,tmp%=x;
tmp*=M;
}
while(!r.n[r.l-1] && r.l>1)--r.l;
return r;
}
//---------------------------------------
}a,b,c;
int main()
{
a.init();
b.init();
c=a+b;
c.print();
c=a-b;
c.print();
c=a*b;
c.print();
c=a/b;
c.print();
return 0;
}