码迷,mamicode.com
首页 > 其他好文 > 详细

大数模版

时间:2016-05-12 16:37:59      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:

动态分配内存,由数的十进制位数决定。效率不是很高,但使用方便

(更多kkke写的模版下载,在http://pan.baidu.com/s/1c26ZuOo)

#ifndef LONGINT_H
#define LONGINT_H

#include <iostream>
#include <cstring>

class longint{
	int *num;
	int len;
	bool sign;
	longint(int *new_num,int new_len,bool new_sign)
	{
		num=new_num;
		len=new_len;
		sign=new_sign;
	}
public:
	~longint();
	longint();
	longint(int a);
	longint(long long a);
	longint(const char *a);
	longint(const std::string &a);
	longint(const longint &a);
	int getlen()const;
	int c_int()const;
	long long c_longlong()const;
	friend std::ostream& operator<<(std::ostream &outs,const longint &a);
	friend std::istream& operator>>(std::istream &ins,longint &a);
	friend longint abs(longint a);
	longint operator-()const;
	longint operator=(const longint &a);
	longint operator=(int a);
	longint operator=(long long a);
	longint operator=(const char *a);
	longint operator=(const std::string &a);
	longint operator+(const longint &a)const;
	longint operator-(const longint &a)const;
	longint operator*(const longint &a)const;
	longint operator/(const longint &a)const;
	longint operator%(const longint &a)const;
	longint operator<<(int a)const;
	longint operator>>(int a)const;
	longint operator^(int k)const;
	longint operator+=(const longint &a);
	longint operator-=(const longint &a);
	longint operator*=(const longint &a);
	longint operator/=(const longint &a);
	longint operator%=(const longint &a);
	longint operator<<=(int a);
	longint operator>>=(int a);
	longint operator^=(int k);
	longint operator++();
	longint operator--();
	longint operator++(int);
	longint operator--(int);
	bool operator<(const longint &a)const;
	bool operator>(const longint &a)const;	
	bool operator<=(const longint &a)const;
	bool operator>=(const longint &a)const;
	bool operator!=(const longint &a)const;
	bool operator==(const longint &a)const;
};

longint longint::operator%=(const longint &a)
{
	return *this=*this%a;
}

longint longint::operator%(const longint &a)const
{
	if(sign)return -( (-(*this)) % abs(a) );
	if(a.sign)return *this%(-a);
	if(*this<a)return *this;
	longint b=(*this)>>(len-a.len);
	while(b>=a)b-=a;
	for(int i=len-a.len-1;i>=0;i--)
	{
		b=(b<<1)+(longint)num[i];
		while(b>=a)b-=a;
	}
	return b;
}

longint longint::operator^=(int k)
{
	*this=(*this)^k;
}

longint longint::operator^(int k)const
{
	longint a=*this,b=1;
	while(k)
	{
		if(k&1)b*=a;
		a*=a;
		k>>=1;
	}
	return b;
}

longint longint::operator/=(const longint &a)
{
	return *this=*this/a;
}

longint longint::operator/(const longint &a)const
{
	if(sign&&a.sign)return (-(*this))/(-a);
	if(sign||a.sign)return -(abs(*this)/abs(a));
	if(*this<a)return (longint)0;
	int new_len=len-a.len+1;
	int *new_num=new int[new_len];
	longint b=(*this)>>(len-a.len);
	new_num[new_len-1]=0;
	while(b>=a)
	{
		b-=a;
		new_num[new_len-1]++;
	}
	for(int i=new_len-2;i>=0;i--)
	{
		b=(b<<1)+(longint)num[i];
		new_num[i]=0;
		while(b>=a)
		{
			b-=a;
			new_num[i]++;
		}
	}
	if(!new_num[new_len-1])new_len--;
	return (longint){new_num,new_len,false};
}

longint longint::operator*=(const longint &a)
{
	return *this=*this*a;
}

longint longint::operator*(const longint &a)const
{
	if(len==1&&num[0]==0)return *this;
	if(a.len==1&&a.num[0]==0)return a;
	int new_len=len+a.len;
	int *new_num=new int[new_len];
	for(int i=0;i<new_len;i++)new_num[i]=0;
	for(int i=0;i<len;i++)
	    for(int j=0;j<a.len;j++)
	        new_num[i+j]+=num[i]*a.num[j];
	for(int i=0;i<new_len;i++)
	{
		if(new_num[i]>=10)
		{
			new_num[i+1]+=new_num[i]/10;
			new_num[i]%=10;
		}
	}
	if(!new_num[new_len-1])new_len--;
	return (longint){new_num,new_len,(sign==a.sign)?false:true};
}

longint abs(longint a)
{
	a.sign=false;
	return a;
}

longint longint::operator<<=(int a)
{
	return *this=(*this)<<a;
}

longint longint::operator>>=(int a)
{
	return *this=(*this)>>a;
}
	
longint longint::operator>>(int a)const
{
	if(a>=len)return (longint)0;
	int new_len=len-a;
	int *new_num=new int[new_len];
	for(int i=0,j=a;j<len;i++,j++)new_num[i]=num[j];
	return (longint){new_num,new_len,sign};
}

longint longint::operator<<(int a)const
{
	if(len==1&&num[0]==0)return *this;
	int new_len=len+a;
	int *new_num=new int[new_len];
	for(int i=0,j=a;i<len;i++,j++)new_num[j]=num[i];
	for(int i=0;i<a;i++)new_num[i]=0;
	return (longint){new_num,new_len,sign};
}

longint longint::operator++()
{
	return *this=*this+1;
}

longint longint::operator--()
{
	return *this=*this-1;
}

longint longint::operator++(int)
{
	return *this=*this+1;
}

longint longint::operator--(int)
{
	return *this=*this-1;
}

longint longint::operator+=(const longint &a)
{
	return *this=*this+a;
}

longint longint::operator-=(const longint &a)
{
	return *this=*this-a;
}

int longint::getlen()const
{
	return len;
}

longint longint::operator-(const longint &a)const
{
	if(*this==a)return (longint)0;
	if(sign!=a.sign)return (*this)+(-a);
	if(sign)
	{
		if(*this>a)return (-a) - (-(*this));
		return -( (-(*this)) - (-a) );
	}
	if(*this<a)return -(a-(*this));
	int new_len=len;
	int *new_num=new int[new_len];
	new_num[0]=0;
	for(int i=0;i<a.len;i++)
	{
		new_num[i]+=num[i]-a.num[i];
		if(new_num[i]<0)
		{
			new_num[i]+=10;
			new_num[i+1]=-1;
		}
		else if(i<len-1)new_num[i+1]=0;
	}
	for(int i=a.len;i<len;i++)
	{
		new_num[i]+=num[i];
		if(new_num[i]<0)
		{
			new_num[i]+=10;
			new_num[i+1]=-1;
		}
		else if(i<len-1)new_num[i+1]=0;
	}
	while(!new_num[new_len-1])new_len--;
	return (longint){new_num,new_len,false};
}

longint longint::operator+(const longint &a)const
{
	if(sign!=a.sign)return (*this)-(-a);
	if(len<a.len)return a+(*this);
	int new_len=len+1;
	int *new_num=new int[new_len];
	new_num[0]=0;
	for(int i=0;i<a.len;i++)
	{
		new_num[i]+=num[i]+a.num[i];
		if(new_num[i]>=10)
		{
			new_num[i]-=10;
			new_num[i+1]=1;
		}
		else new_num[i+1]=0;
	}
	for(int i=a.len;i<len;i++)
	{
		new_num[i]+=num[i];
		if(new_num[i]>=10)
		{
			new_num[i]-=10;
			new_num[i+1]=1;
		}
		else new_num[i+1]=0;
	}
	if(!new_num[new_len-1])new_len--;
	return (longint){new_num,new_len,sign};
}

bool longint::operator!=(const longint &a)const
{
	if(sign!=a.sign)return true;
	if(len!=a.len)return true;
	for(int i=0;i<len;i++)
	    if(num[i]!=a.num[i])
	        return true;
	return false;
}

bool longint::operator==(const longint &a)const
{
	if(sign!=a.sign)return false;
	if(len!=a.len)return false;
	for(int i=0;i<len;i++)
	    if(num[i]!=a.num[i])
	        return false;
	return true;
}

bool longint::operator>(const longint &a)const
{
	return a<*this;
}

bool longint::operator>=(const longint &a)const
{
	return !(*this<a);
}

bool longint::operator<=(const longint &a)const
{
	return !(a<*this);
}

bool longint::operator<(const longint &a)const
{
	if(sign&&a.sign)
	{
		if(len<a.len)return false;
	    if(len>a.len)return true;
	    for(int i=len-1;i>=0;i--)
	    {
	    	if(num[i]<a.num[i])return false;
	    	if(num[i]>a.num[i])return true;
	    }
	    return false;
	}
	if(sign)return true;
	if(a.sign)return false;
	if(len<a.len)return true;
	if(len>a.len)return false;
	for(int i=len-1;i>=0;i--)
	{
	    if(num[i]<a.num[i])return true;
	    if(num[i]>a.num[i])return false;
	}
	return false;
}

long long longint::c_longlong()const
{
	long long a=0LL;
	for(int i=len-1;i>=0;i--)a=a*10LL+num[i];
	return a;
}

int longint::c_int()const
{
	int a=0;
	for(int i=len-1;i>=0;i--)a=a*10+num[i];
	return a;
}

longint longint::operator-()const
{
	if(len==1&&num[0]==0)return *this;
	longint a=*this;
	a.sign=!sign;
	return a;
}

longint longint::operator=(const std::string &a)
{
	return *this=a.c_str();
}


longint longint::operator=(int a)
{
	if(num)delete[] num;
	if(!a)
	{
		num=new int[1];
		num[0]=0;
		len=1;
		sign=false;
		return *this;
	}
	num=new int[20];
	if(a<0)
	{
		sign=true;
		a=-a;
	}
	else sign=false;
	len=0;
	while(a)
	{
		num[len]=a%10;
		len++;
		a/=10;
	}
	return *this;
}


longint longint::operator=(long long a)
{
	if(num)delete[] num;
	if(!a)
	{
		num=new int[1];
		num[0]=0;
		len=1;
		sign=false;
		return *this;
	}
	num=new int[40];
	if(a<0LL)
	{
		sign=true;
		a=-a;
	}
	else sign=false;
	len=0;
	while(a)
	{
		num[len]=a%10LL;
		len++;
		a/=10LL;
	}
	return *this;
}

longint longint::operator=(const char *a)
{
	if(a[0]=='-')
	{
		sign=true;
		a++;
	}
	else sign=false;
	len=strlen(a);
	if(num)delete[] num;
	num=new int[len];
	for(int i=0,j=len-1;i<len;i++,j--)num[i]=a[j]-'0';
	return *this;
}

longint longint::operator=(const longint &a)
{
	if(num)delete[] num;
	num=new int[a.len];
	sign=a.sign;
	len=a.len;
	for(int i=0;i<len;i++)num[i]=a.num[i];
	return *this;
}

longint::longint()
{
	num=NULL;
}

longint::~longint()
{
    if(num)delete[] num;
}

longint::longint(const char *a)
{
	if(a[0]=='-')
	{
		sign=true;
		a++;
	}
	else sign=false;
	len=strlen(a);
	num=new int[len];
	for(int i=0,j=len-1;i<len;i++,j--)num[i]=a[j]-'0';
}

longint::longint(int a)
{
	if(!a)
	{
		num=new int[1];
		num[0]=0;
		len=1;
		sign=false;
		return;
	}
	num=new int[20];
	if(a<0)
	{
		sign=true;
		a=-a;
	}
	else sign=false;
	len=0;
	while(a)
	{
		num[len]=a%10;
		len++;
		a/=10;
	}
}

longint::longint(long long a)
{
	if(!a)
	{
		num=new int[1];
		num[0]=0;
		len=1;
		sign=false;
		return;
	}
	num=new int[40];
	if(a<0)
	{
		sign=true;
		a=-a;
	}
	else sign=false;
	len=0;
	while(a)
	{
		num[len]=a%10;
		len++;
		a/=10;
	}
}

longint::longint(const std::string &a)
{
	num=NULL;
	*this=a.c_str();
}

longint::longint(const longint &a)
{
	num=new int[a.len];
	sign=a.sign;
	len=a.len;
	for(int i=0;i<len;i++)num[i]=a.num[i];
}

std::ostream& operator<<(std::ostream &outs,const longint &a)
{
	if(a.sign)outs<<'-';
	for(int i=a.len-1;i>=0;i--)outs<<a.num[i];
	return outs;
}

std::istream& operator>>(std::istream &ins,longint &a)
{
	std::string data;
	ins>>data;
	a=data;
	return ins;
}

#endif


    上面的乘法直接用的普通O(n^2)的方法,还有一种递归实现的O(n^(1.5))的方法,不过实际情况看来并没有多大优化,而且很占空间。

    思想就是每次将两个数分别分成前半部分和后半部分,两两分别相乘,递归处理,直到位数小于一定值就直接转换为int型再乘。

longint longint::operator*(const longint &a)const
{
	if(len<9&&a.len<9)return c_longlong()*a.c_longlong();
	if(len==1&&num[0]==0)return *this;
	if(a.len==1&&a.num[0]==0)return a;
	int n=std::max(len,a.len)>>1;
	//XY=AC<<2n+[(A-B)(D-C)+AC+BD]<<n+BD;
	longint A=(*this)>>n;
	longint B=(*this)-(A<<n);
	longint C=a>>n;
	longint D=a-(C<<n);
	longint AC=A*C;
	longint BD=B*D;
	return (AC<<(2*n))+( ( (A-B)*(D-C)+AC+BD ) <<n)+BD;
}



大数模版

标签:

原文地址:http://blog.csdn.net/tookkke/article/details/51366490

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!