高精度运算

来源:互联网 发布:单片机串口是什么 编辑:程序博客网 时间:2024/05/16 09:38

通用版高精度运算类。长度限制为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>yif(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;}

0 0
原创粉丝点击