c++高精度类

头文件 - intx.h

//intx.h
#ifndef INTX_H_
#define INTX_H_
#include <iostream>
#include <cstring>
#include <string>
class intx
{
private:
	bool sign;
	int *num;
	int len;
	static int process_char(const char *s,bool &sign,int *&num);
	static bool unsign_gt(const int *a,const int lena,const int *b,const int lenb);
	static bool unsign_gte(const int *a,const int lena,const int *b,const int lenb);
	static int unsign_plus(const int *a,int lena,const int *b,int lenb,int *&result);
	static int unsign_minus(const int *a,int lena,const int *b,int lenb,int *&result);
	static int multiply_base(const int *a,const int lena,int n,int *&result);
	static int unsgin_multiply(const int *a,const int lena,const int *b,const int lenb,int *&result);
	static bool divide_gte(const int *a,int end,const int *b,int lenb);
	static int unsign_divide(const int *a,const int lena,const int *b,const int lenb,int *&result);
	static int unsign_mod(const int *a,const int lena,const int*b,const int lenb,int *&result);
public:
//constructor
	intx();
	intx(const char * s);
	intx(const std::string & str);
	intx(int n);
	intx(const intx &b);
//destructor
	~intx();
//calc
	bool operator==(const intx &b) const;
	bool operator>(const intx &b) const;
	bool operator>=(const intx &b) const;
	bool operator<(const intx &b) const;
	bool operator<=(const intx &b) const;
	intx operator-()const;
	intx operator+(const intx &b) const;
	intx operator-(const intx &b) const;
	intx operator*(const intx &b) const;
	intx operator/(const intx &b) const;
	intx operator%(const intx &b) const;
//others
	friend std::ostream& operator<<(std::ostream &os,const intx &a);
	friend std::istream& operator>>(std::istream &is,intx &a);
	int& operator[](const int sub) const;
	intx& operator=(const intx &b);
	intx& operator=(const char *s);
	intx& operator=(const std::string &str);
	int size(){return len;}
	bool IsNatural()const{return sign;}
};
#endif

实现文件 - intx.cpp

//intx.cpp
#include "intx.h"

//private
int intx::process_char(const char *s,bool &sign,int *&num)
{
	int len = strlen(s);
	if(!len)//len == 0
	{
		sign = true;
		num = new int[1];
		num[0] = 0;
		len = 1;
	}
	else
		switch(s[0])
		{
		case '+':
			sign = true;
			--len;
			num = new int[len];
			for(int i = 0;i < len;++i)
				num[i] = s[i + 1] - '0';
			break;
		case '-':
			sign = false;
			--len;
			num = new int[len];
			for(int i = 0;i < len;++i)
				num[i] = s[i + 1] - '0';
			break;
		default:
			sign = true;
			num = new int[len];
			for(int i = 0;i < len;++i)
				num[i] = s[i] - '0';
			break;
		}
	return len;
}
bool intx::unsign_gt(const int *a,const int lena,const int *b,const int lenb)
{
	if(lena < lenb)
		return false;
	else if(lena > lenb)
		return true;
	else
	{
		for(int i = 0;i < lena;++i)
			if(a[i] < b[i])
				return false;
			else if(a[i] > b[i])
				return true;
		return false;
	}
}
bool intx::unsign_gte(const int *a,const int lena,const int *b,const int lenb)
{
	if(lena < lenb)
		return false;
	else if(lena > lenb)
		return true;
	else
	{
		for(int i = 0;i < lena;++i)
			if(a[i] < b[i])
				return false;
			else if(a[i] > b[i])
				return true;
		return true;
	}
} 
int intx::unsign_plus(const int *a,int lena,const int *b,int lenb,int *&result)
{
	int rem;
	if(lenb > lena)
	{
		const int *temp = a;
		a = b;
		b = temp;
		rem = lena;
		lena = lenb;
		lenb = rem;
	}
	int len = lena + 1;
	result = new int[len];
	int sub = lena;
	rem = 0;
	--lena;
	--lenb;
	while(lenb >= 0)
	{
		rem += a[lena--] + b[lenb--];
		result[sub--] = rem % 10;
		rem /= 10;
	}
	while(lena >= 0)
	{
		rem += a[lena--];
		result[sub--] = rem %10;
		rem /= 10;
	}
	if(rem > 0)
	{
		result[sub] = rem;
	}
	else
	{
		--len;
		int *p = new int[len];
		memcpy(p,result + 1,sizeof(int)*len);
		delete[] result;
		result = p;
	}
	return len;
}
int intx::unsign_minus(const int *a,int lena,const int *b,int lenb,int *&result)//a must > b
{
	int len = lena;
	result = new int[len];
	memcpy(result,a,sizeof(int)*len);//const int *a can't modify
	--lenb;
	--lena;
	while(lenb >= 0)
	{
		if(a[lena] >= b[lenb])
			result[lena] -= b[lenb];
		else
		{
			result[lena] += 10 - b[lenb];
			--result[lena -1];
		}
		--lena;
		--lenb;
	}
	while(lena>=0)
	{
		if(result[lena] < 0)
		{
			result[lena] += 10;
			--result[lena - 1];
			--lena;
		}
		else
			break;
	}
	int zero = 0;
	while(zero < len)
		if(result[zero] == 0)
			++zero;
		else
			break;
	if(zero == len)
	{
		delete[] result;
		result = new int[1]{0};
		len = 1;
	}
	else if(zero != 0)
	{
		len -= zero;
		int *p = new int[len];
		memcpy(p,result + zero,sizeof(int)*len);
		delete[] result;
		result = p;
	}
	return len;
}
bool intx::divide_gte(const int *a,const int end,const int *b,const int lenb)
{
	int begin = 0;
	while(a[begin] == 0)
	{
		++begin;
	}
	if(end - begin  + 1 < lenb)
		return false;
	else if(end - begin + 1 > lenb)
		return true;
	else
	{
		for(int i = 0;i < lenb;++begin,++i)
			if(a[begin] > b[i])
				return true;
			else if(a[begin] < b[i])
				return false;
		return true;
	}
}
int intx::multiply_base(const int *a,int lena,const int n,int * &result)//the first may be 0
{
	int len = lena + 1;
	result = new int[len];
	int rem = 0;
	int sub = lena;
	--lena;
	while(lena >= 0)
	{
		rem += n * a[lena];
		result[sub] = rem % 10;
		rem /= 10;
		--lena;
		--sub;
	}
	if(rem > 0)
		result[sub] = rem;
	else
		result[sub] = 0;
	return len;
}
int intx::unsgin_multiply(const int *a,const int lena,const int *b,const int lenb,int *&result)//a on the top
{
	int len = lena + lenb;
	result = new int[len]{0};
	int *MultiplyTemp;
	int MultiplyBit = lenb - 1;//the subscript of number in the b to be multiplied
	while(MultiplyBit >= 0)
	{
		int MultiplyTempSub = multiply_base(a,lena,b[MultiplyBit],MultiplyTemp);
		//plus
		int rem = 0;
		int sub = len - (lenb - MultiplyBit);//the bit when result begin plus
		--MultiplyTempSub;
		while(MultiplyTempSub >= 0)
		{
			rem += result[sub] + MultiplyTemp[MultiplyTempSub];
			result[sub] = rem % 10;
			rem /= 10;
			--sub;
			--MultiplyTempSub;
		}
		if(rem > 0)
			result[sub] += rem;
		--MultiplyBit;
		delete[] MultiplyTemp;
	}
	int zero = 0;
	while(zero < len)
		if(result[zero] == 0)
			++zero;
		else
			break;
	if(zero == len)
	{
		delete[] result;
		result = new int[1]{0};
		return 1;
	}
	else if(zero != 0)
	{
		len -= zero;
		int *p = new int[len];
		memcpy(p,result + zero,sizeof(int)*len);
		delete[] result;
		result = p;
	}	
	return len;
}
int intx::unsign_divide(const int *a,const int lena,const int *b,const int lenb,int *&result)
{
	if(lena < lenb)
	{
		result = new int[1]{0};
		return 1;
	}
	//Judge the first bit
	int CurrentBit = lenb - 1;//the current number on the consult
	int len;
	if(!divide_gte(a,CurrentBit,b,lenb))
		if(CurrentBit + 1== lena)//lena == lenb && a < b
		{
			result = new int[1]{0};
			return 1;
		}
		else
		{
			++CurrentBit;
			len = lena - lenb;
			result = new int[len];
		}
	else
	{
		len = lena - lenb + 1;
		result = new int[len];
	}
	//copy
	int *A = new int[lena];
	memcpy(A,a,sizeof(int)*lena);
	int sub = 0;//sub = CurrentBit - (lena - lenb),too much calc
	while(CurrentBit < lena)
	{
		result[sub] = 0;
		do
		{
			//minus
			int Asub = CurrentBit;
			for(int i = lenb - 1;i >= 0;--Asub,--i)
				if(A[Asub] >= b[i])
					A[Asub] -= b[i];
				else
				{
					A[Asub] += 10 - b[i];
					--A[Asub - 1];
				}
			while(Asub >= 0)
				if(A[Asub] < 0)
				{
					A[sub] += 10;
					--A[Asub - 1];
					--Asub;
				}
				else
					break;
			++result[sub];
		}while(divide_gte(A,CurrentBit,b,lenb));
		if(++sub,++CurrentBit == lena)
			break;
		while(!divide_gte(A,CurrentBit,b,lenb))
		{
			result[sub] = 0;
			if(++sub,++CurrentBit == lena)
				break;
		}
	}
	delete[]A;
	return len;
}
int intx::unsign_mod(const int *a,const int lena,const int *b,const int lenb,int *&result)
{
	int len = lena;
	result = new int[len];
	memcpy(result,a,sizeof(int)*len);
	if(lena < lenb)
		return len;
	//Judge the first bit
	int CurrentBit = lenb - 1;//the current number on the consult
	if(!divide_gte(result,CurrentBit,b,lenb))
	{
		if(CurrentBit + 1== len)//lena == lenb && a < b
			return len;
		else
			++CurrentBit;
	}
	while(CurrentBit < len)
	{
		do
		{
			//minus
			int sub = CurrentBit;
			for(int i = lenb - 1;i >= 0;--sub,--i)
				if(result[sub] >= b[i])
					result[sub] -= b[i];
				else
				{
					result[sub] += 10 - b[i];
					--result[sub - 1];
				}
			while(sub >= 0)
				if(result[sub] < 0)
				{
					result[sub] += 10;
					--result[sub - 1];
					--sub;
				}
				else
					break;
		}while(divide_gte(result,CurrentBit,b,lenb));
		while(++CurrentBit != len)
			if(divide_gte(result,CurrentBit,b,lenb))
				break;
	}
	int zero = 0;
	while(zero < len)
		if(result[zero] == 0)
			++zero;
		else
			break;
	if(zero == len)
	{
		delete[] result;
		result = new int[1]{0};
		len = 1;
	}
	else if(zero != 0)
	{
		len -= zero;
		int *p = new int[len];
		memcpy(p,result + zero,sizeof(int)*len);
		delete[] result;
		result = p;
	}
	return len;
}
//constructor
intx::intx()
{
	sign = true;
	num = new int[1];
	num[0] = 0;
	len = 1;
}
intx::intx(const char *s)
{
	len = process_char(s,sign,num);
}
intx::intx(const std::string &str)
{
	const char *s = str.data();
	new (this)intx(s); 
}
intx::intx(int n)
{
	if(n < 0)
		sign = false;
	else
		sign = true;
	if(n == 0)
	{
		len = 1;
		num = new int[1]{0};
		return;
	}
	len = 0;
	int N = n;
	while(n > 0)
	{
		n /= 10;
		++len;
	}
	num = new int[len];
	for(int i = len;i > 0;--i)
	{
		num[i - 1] = N % 10;
		N /= 10;
	}
}
intx::intx(const intx &b)
{
	sign = b.sign;
	len =  b.len;
	num = new int[len];
	memcpy(num,b.num,sizeof(int) * len);
}
//destructor
intx::~intx()
{
	delete[] num;
}

//calc
bool intx::operator==(const intx &b) const
{
	if(len != b.len)
		return false;
	else if(sign != b.sign)
		return false;
	else
	{
		for(int i = 0;i < len;++i)
			if(num[i] != b.num[i])
				return false;
		return true;
	}
}
bool intx::operator>(const intx &b) const
{
	if(sign)
		if(b.sign)
			return unsign_gt(num,len,b.num,b.len);
		else
			return true;
	else
		if(b.sign)
			return false;
		else
			return !unsign_gt(num,len,b.num,b.len);
}
bool intx::operator>=(const intx &b)const
{
	if(sign)
		if(b.sign)
			return unsign_gte(num,len,b.num,b.len);
		else
			return true;
	else
		if(b.sign)
			return false;
		else
			return !unsign_gte(num,len,b.num,b.len);
}
bool intx::operator<(const intx &b) const
{
	return !(*this >= b);
}
bool intx::operator<=(const intx &b) const
{
	return !(*this > b);
}
intx intx::operator-()const
{
	intx b = *this;
	b.sign = !b.sign;
	return b;
}
intx intx::operator+(const intx &b) const
{
	intx sum;
	delete[] sum.num;
	if(sign)//a >= 0
		if(b.sign)//a > 0 && b > 0
		{
			sum.sign = true;
			sum.len = unsign_plus(num,len,b.num,b.len,sum.num);
		}
		else if(unsign_gte(num,len,b.num,b.len))// a > 0,b < 0,|a| >= |b|
		{
			sum.sign = true;
			sum.len = unsign_minus(num,len,b.num,b.len,sum.num);
		}
		else// a > 0,b < 0,|a| < |b|
		{
			sum.sign = false;
			sum.len = unsign_minus(b.num,b.len,num,len,sum.num);
		}
	else//a < 0
	{
		if(!b.sign)// a < 0, b < 0
		{
			sum.sign = false;
			sum.len = unsign_plus(num,len,b.num,b.len,sum.num);
		}
		else if(unsign_gte(b.num,b.len,num,len))// a < 0,b > 0,|a| <= |b|
		{
			sum.sign = true;
			sum.len = unsign_minus(b.num,b.len,num,len,sum.num);
		}
		else//a < 0 b > 0 , |a| > |b|
		{
			sum.sign = false;
			sum.len = unsign_minus(num,len,b.num,b.len,sum.num);
		}
	}
	return sum;
}
intx intx::operator-(const intx &b)const
{
	return *this + (-b);
}
intx intx::operator*(const intx &b)const
{
	intx product;
	if(sign == b.sign)
		product.sign = true;
	else
		product.sign = false;
	delete[] product.num;
	product.len = unsgin_multiply(num,len,b.num,b.len,product.num);
	return product;
}
intx intx::operator/(const intx &b) const
{
	intx consult;
	if(sign == b.sign)
		consult.sign = true;
	else
		consult.sign = false;
	delete[] consult.num;
	consult.len = unsign_divide(num,len,b.num,b.len,consult.num);
	if(consult[0] == 0)//avoid "-0"
		consult.sign = true;
	return consult;
}
intx intx::operator%(const intx &b)const
{
	intx modulo;
	delete[] modulo.num;
	modulo.sign = sign;
	modulo.len = unsign_mod(num,len,b.num,b.len,modulo.num);
	return modulo;
}
//others
std::ostream& operator<<(std::ostream &os,const intx &a)
{
	if(!a.sign)
		os << '-';
	for(int i = 0;i < a.len;++i)
		os << a.num[i];
	return os;
}
std::istream& operator>>(std::istream &is,intx &a)
{
	delete[] a.num;
	int max = 16;
	a.num = new int[max];
	//Judge sign
	char c;
	a.len = 0;
	c = getchar();
	if(c == '-')
		a.sign = false;
	else if(c == '+')
		a.sign = true;
	else if(c <= '9' && c >= '1')//the first num
	{
		a.num[a.len] = c - '0';
		++a.len;
	}
	else
	{
		a.sign = true;
		a.num[a.len] = 0;
		++a.len;
		return is;
	}
	//makesure the first bit is inputed
	if(a.len == 0)
	{
		c = getchar();
		if(c >= '1' && c <= '9')
		{
			a.num[a.len] = c - '0';
			++a.len;
		}
		else
		{
			a.sign = true;
			a.num[a.len] = 0;
			++a.len;
			return is;
		}
	}
	while(c = is.peek(),c >= '0' && c <= '9')
	{
		is >> c;
		a.num[a.len] = c - '0';
		if(++a.len == max)
		{
			max *= 2;
			int *temp = new int[max];
			memcpy(temp,a.num,sizeof(int)*a.len);
			delete[] a.num;
			a.num = temp;
		}
	}
	return is;
}
int & intx::operator[](const int sub) const
{
	return num[len - 1 - sub];
}
intx& intx::operator=(const intx &b)
{
	if(this == &b)
		return *this;
	else
	{
		len = b.len;
		sign = b.sign;
		delete[] num;
		num = new int[len];
		memcpy(num,b.num,sizeof(int) * len);
		return *this;
	}
}
intx& intx::operator=(const char *s)
{
	delete[] num;
	len = process_char(s,sign,num);
	return *this;
}
intx& intx::operator=(const std::string &str)
{
	delete[] num;
	len = process_char(str.data(),sign,num);
	return *this;
}
posted @ 2018-01-27 15:14  h_hg  阅读(1324)  评论(0编辑  收藏  举报