高精度运算

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

你可能感兴趣的:(C++,高精度运算,大整数加减乘除,高精度比较,大整数比较)