• 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;
    }
    
  • 相关阅读:
    Java基础系列(3)- 程序流程控制
    Linux 文本处理三剑客
    POJ3592 Instantaneous Transference题解
    插入排序的优化非希尔【不靠谱地讲可以优化到O(nlogn)】 USACO 丑数
    BZOJ2818 与 BZOJ2301【euler,线性筛,莫比乌斯】
    BZOJ1857 传送带 (三分法求单峰函数极值)
    线段树详解
    二叉查找树 详解
    最小函数值 洛谷P2085
    二叉树的遍历转换(层序,中序转先序)
  • 原文地址:https://www.cnblogs.com/h-hg/p/8366142.html
Copyright © 2020-2023  润新知