通用版高精度运算类。长度限制为1000,可以通过修改程序中的maxn变量修改长度限制
功能:1.大整数加法,正负皆可
2.大整数减法,正负皆可
3.大整数除法,除数不能为0,正负皆可,只支持整数运算如1000/999=1.
4.大整数乘法,两个整数长度的乘积不超过1000,正负皆可
5.重载了输入输出运算符,可直接对大整数进行输入输出
6.重载了比较运算符,可直接对大整数进行比较
7.可直接以bign a=1,bign a="123",的形式对大整数进行初始化
小算法:加法,减法,乘法皆为模范手动计算,把手动计算的方法作为算法,而除法我这里使用了类似二分查找法的算法,例如,x=29873,y=234,假设计算x/y,则令high=max(x,y),low=1,mid=(high+low)/2;用mid*y去逼近x。这只是粗略的描述了我的计算方法,当然有很多要注意的问题,例如当x<y时怎么处理,具体算法看代码。
ps: 若有错误欢迎指正。
代码:
#include "stdafx.h" #include <string> #include <iostream> #include <assert.h> #include <fstream> using namespace std; const int maxn=1000; class bign { friend istream & operator >> (istream &in,bign &x); friend ostream & operator << (ostream &out,bign &x); public: bign() {//构造初始值为0的高精度数 memset(f,0,sizeof(f)); len=1;//初始值为0 } bign(const char *s) {//c字符串常量初始化当前对象 memset(f,0,sizeof(f)); *this=s; } bign(const string s) { memset(f,0,sizeof(f)); *this=s; } bign(int num) { memset(f,0,sizeof(f)); *this=num; } bign operator=(const char *s) { memset(f,0,sizeof(f)); int i,j=0; int slen=strlen(s); if(s[0]=='-') len=slen-1; else len=slen; for(i=slen-1,j=0;i>=0;i--,j++){ if(i==0 && s[i]=='-'){//输入的是负数 f[j-1]=-f[j-1]; break; } f[j]=s[i]-'0'; //cout<<"f[j]="<<f[j]<<",f[i]="<<s[i]<<endl; } // cout<<len<<" "<<f[len-1]<<endl; return *this; } bign operator=(int num) {//重载= char buf[maxn]; memset(buf,'\0',sizeof(buf)); sprintf(buf,"%d",num); *this=buf; return *this; } bign operator=(const bign &x) {//重载= memset(f,0,sizeof(f)); (*this).len=x.len; for(int i=0;i<x.len;i++) (*this).f[i]=x.f[i]; return *this; } bign operator = (const string s) {//重载= const char *buf=s.c_str(); *this=buf; return *this; } bign operator +(const bign x) const {//重载+ if(this->f[this->len-1]>0 && x.f[x.len-1]>0) return add(*this,x);//两数都为正 else if(this->f[this->len-1] < 0 && x.f[x.len-1]<0){//两数都为负 bign tx=x,ty=*this; tx.f[tx.len-1]=-tx.f[tx.len-1]; ty.f[ty.len-1]=-ty.f[ty.len-1]; bign res=add(tx,ty); res.f[res.len-1]=-res.f[res.len-1]; return res; }else { bign tx=*this,ty=x,res; if(tx.f[tx.len-1]<0){ tx.f[tx.len-1]=-tx.f[tx.len-1];//若<0先让其变为正数 if(tx>ty){ res=sub(tx,ty); res.f[res.len-1]=-res.f[res.len-1]; }else{ res=sub(ty,tx); } }else{ ty.f[ty.len-1]=-ty.f[ty.len-1];//若<0先让其变为正数 if(ty>tx){ res=sub(ty,tx); res.f[res.len-1]=-res.f[res.len-1]; // cout<<"res.f[res.len-1]="<<res.f[res.len-1]<<endl; }else{ res=sub(tx,ty); } } return res; } } bign operator +=(const bign x) {//重载+= *this=*this+x; return *this; } bign operator -(const bign x) const {//重载- bign tx=x; tx.f[tx.len-1]=-tx.f[tx.len-1]; //cout<<"x.f[x.len-1]="<<x.f[x.len-1]<<endl; return *this+tx; } bign operator *(const bign x) const {//重载* if(this->f[this->len-1]>0 && x.f[x.len-1]>0) return mul(*this,x);//两数都为正 else if(this->f[this->len-1] < 0 && x.f[x.len-1]<0){//两数都为负 bign tx=*this,ty=x; tx.f[tx.len-1]=-tx.f[tx.len-1]; ty.f[ty.len-1]=-ty.f[ty.len-1]; return mul(tx,ty); }else{//两数异号 bign tx=*this,ty=x,res; if(tx.f[tx.len-1]<0){ tx.f[tx.len-1]=-tx.f[tx.len-1];//若<0先让其变为正数 }else{ ty.f[ty.len-1]=-ty.f[ty.len-1];//若<0先让其变为正数 } res=mul(tx,ty); res.f[res.len-1]=-res.f[res.len-1]; return res; } } bign operator /(const bign x) { if(x==bign(0)) abort(); if(this->f[this->len-1]>0 && x.f[x.len-1]>0) return div(*this,x);//两数都为正 else if(this->f[this->len-1] < 0 && x.f[x.len-1]<0){//两数都为负 bign tx=*this,ty=x; tx.f[tx.len-1]=-tx.f[tx.len-1]; ty.f[ty.len-1]=-ty.f[ty.len-1]; return div(tx,ty); }else{//两数异号 bign tx=*this,ty=x,res; if(tx.f[tx.len-1]<0){ tx.f[tx.len-1]=-tx.f[tx.len-1];//若<0先让其变为正数 }else{ ty.f[ty.len-1]=-ty.f[ty.len-1];//若<0先让其变为正数 } res=div(tx,ty); res.f[res.len-1]=-res.f[res.len-1]; return res; } } bign operator -=(const bign x) {//重载-= *this=*this-x; return *this; } bool operator < (const bign x) const {//< if(f[len-1]*x.f[x.len-1]<0) return f[len-1]<0? true:false;//异号 if(f[len-1]>0){//都>0 if(len<x.len) return true; if(len>x.len) return false; for(int i=len-1;i>=0;--i){ if(f[i]> x.f[i]) return false; if(f[i]==x.f[i]) continue; if(f[i]<x.f[i]) return true; } return false; }else if(f[len-1]<0){//都<0 if(len<x.len) return false; if(len>x.len) return true; if(f[len-1] > x.f[len-1]) return false;//比较负数最高位 for(int i=len-2;i>=0;--i){ if(f[i] > x.f[i]) return true; if(f[i]==x.f[i]) continue; if(f[i]<x.f[i]) return false; } return false; }else{//0 if(x.f[x.len-1]>0) return true; else return false; } } bool operator > (const bign x) const {//> return x<*this; } bool operator >= (const bign x)const {//>= return !(*this<x); } bool operator <= (const bign x)const {//<= return !(*this>x); } bool operator != (const bign x)const {//!= return (x>*this) || (x<*this); } bool operator == (const bign x)const {//== return (x>=*this) && (x<=*this); } string str() { string s; for(int i=len-1;i>=0;i--) { if(f[i]<0){ s+="-"; s+=(f[i]*(-1)+'0'); }else{ s+=(f[i]+'0'); } } return s; } void clear() { memset(f,0,sizeof(f)); len=1;//初始值为0 } private: int len; int f[maxn]; bign add(const bign x,const bign y) const {//res=x+y,两个正数相加 bign res; int i; int c=0; int n=max(x.len,y.len);//最长位数的后一位 // cout<<"len="<<len<<",x.len="<<x.len<<",n="<<n<<endl; // cout<<"len="<<len<<",y.len="<<y.len<<",n="<<n<<endl; for(i=0;i<n;i++){ res.f[i]=(x.f[i]+y.f[i]+c)%10; c=(x.f[i]+y.f[i]+c)/10; // cout<<"res.f[i]="<<res.f[i]<<" c="<<c<<endl; } // cout<<"len="<<len<<",x.len="<<x.len<<",n="<<n<<endl; //for(i=n;i>=0;i--) if(res.f[i]) break; res.len=n; if(c){ res.f[n]=c; res.len+=1; } return res; } bign sub(const bign &x,const bign &y) const {//res=x-y,其中必须x>y if(x<y) abort(); bign res; int i; int c=0; int n=max(x.len,y.len); // cout<<"n="<<n<<endl; for(i=0;i<n;i++){ // cout<<"x.f[i]+c="<<x.f[i]+c<<" y.f[i]="<<y.f[i]<<endl; res.f[i]=(x.f[i]+c)>=y.f[i] ? (x.f[i]-y.f[i]+c)%10 : (x.f[i]-y.f[i]+c+10)%10 ; // cout<<"res.f[i]="<<res.f[i]<<endl; c=(x.f[i]+c)>=y.f[i]? 0:-1; // cout<<"c="<<c<<endl; } // for(i=n;i>=0;i--) if(res.f[i]) break; // res.len = i<=0? 1:i+1;//如果y=0,y.len=1; res.len=n; if(!res.f[n-1] && res.len!=1) res.len-=1; return res; } bign mul(const bign &x,const bign &y) const {//两个整数相乘,x.len*y.len<maxn;否则程序退出 bign res; if(x.len*y.len>=maxn) abort(); int c=0;//表示进位 int k=0; for(int i=0;i<y.len;i++){//y的每一位与x乘 c=0;k=i; for(int j=0;j<x.len;j++){ int temp=res.f[k]+x.f[j]*y.f[i]+c; res.f[k]=temp%10; //cout<<"res.f["<<k<<"]="<<res.f[k]<<endl; c=temp/10; //cout<<"c="<<c<<endl; k++; } if(c) {//最后一个进位 res.f[k]=c; } } res.len=k; if(c) {//最后一个进位 res.f[k]=c; res.len+=1; } return res; } bign divBy2() const {//除以2,即一半 bign res; res.len=len; int j=res.len-1,k=0; int t; for(int i=len-1;i>=0;--i){ t= (f[i]+k)/2; res.f[j--]=t; k=(f[i]+k)%2*10; } if(!(f[len-1]/2)) if(len>1) res.len=len-1; else res.len=1; return res; } bign div(const bign &x,const bign &y) const {//两个正数相除 if(x<y) return bign(0); bign low=bign(1),high=x; bign mid = (low+high).divBy2(); bool high_exist=false; while(low<=high){ high_exist=false; bign tx=x,ty=y; // cout<<"0----->tx="<<tx<<" ty="<<ty<<endl; // cout<<"3---->low="<<low<<" high="<<high<<" mid="<<mid<<endl; if(mid*y > x){ high=mid-bign(1); // cout<<"1---->mid*y="<<mid*y<<" high="<<high<<endl; high_exist=true;//while循环因为high-1而导致high>low退出 } else if(mid*y < x){ low=mid+bign(1); // cout<<"2---->mid*y="<<mid*y<<" "<<mid<<"+"<<bign(1)<<"="<<mid+bign(1)<<" low="<<low<<endl; } else { break; } mid=(low+high).divBy2(); // cout<<"*****low+high*****"<<low<<"+"<<high<<" = " <<low+high<<" (low+high)/2 = "<<mid<<endl; } if(high_exist) return high; return mid; } }; istream & operator >> (istream &in, bign &x) { string s; in>>s; x.clear(); x=s; return in; } ostream & operator << (ostream &out,bign &x) { string s=x.str(); out<<s; return out; }