⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arithmetic.cpp

📁 可进行大数的加减乘除、阶乘、三角函数、幂指数(指数只支持整数)的运算
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "Arithmetic.h"
#include <vector>

long Arithmetic::m_precision = 15;//精度
int Arithmetic::m_Tstate = 0;//计算三角函数时 0表示数值为角度, 2表示数值为弧度
std::string Arithmetic::pai = "3.1415926535897932";//π
/*******************************************************\
函数: Arithmetic构造函数
功能: 初始化空字符串
输入: 无
输出: 无
返回: 无
备注: 无
\*******************************************************/
Arithmetic::~Arithmetic()
{
	m_num = "";
	m_Tstate = 0;
}
/*******************************************************\
函数: Arithmetic构造函数
功能: 赋值
输入: 字符串
输出: 无
返回: 无
备注: 无
\*******************************************************/
Arithmetic::Arithmetic()
{
	m_num = "";
}
Arithmetic::Arithmetic(std::string num)
{
	m_num = num;
}
Arithmetic::Arithmetic(char c)
{
	char a[2];
	a[0] = c;
	a[1] = '\0';
	m_num = a;
}
/*******************************************************\
函数: Arithmetic构造函数
功能: 赋值
输入: 字符串
输出: 无
返回: 无
备注: 无
\*******************************************************/
Arithmetic::Arithmetic(const Arithmetic& data)// const
{
	m_num = data.GetData();
}
/*******************************************************\
函数: Atol
功能: 字符转数字
输入: 字符
输出: 无
返回: 字符对应的数字
备注: 无
\*******************************************************/
int Arithmetic::Atol(char c)
{
	return c - '0';
}

/*******************************************************\
函数: Compare
功能: 比较数字大小
输入: 字符串
输出: 无
返回: 0 一样大, 1 左边大, 2 右边大
备注: 无
\*******************************************************/
int Arithmetic::Compare(std::string& left, std::string& right)
{
	int i;
	for (i = 0;i < left.length() && left[i] == right[i];++i);
	if(i == left.length())
		return 0;
	return left[i] > right[i] ? 1 : 2;
}
/*******************************************************\
函数: SumCarry
功能: 加减法时进位退位
输入: 2个位数之和,进位退位数.
输出: 无
返回: 无
备注: 无
\*******************************************************/
void Arithmetic::SumCarry(int& sum, int& carry)
{
	if(sum < 0)
	{
		sum += 10;
		carry = -1;
		return;
	}
	if(sum >= 10)
	{
		sum -= 10;
		carry = 1;
		return;
	}
	if(sum < 10 && sum >= 0)
		carry = 0;
}
/*******************************************************\
函数: Operation
功能: 加减运算
输入: 2个大数, plus判断加减运算, state判断状态
输出: 无
返回: 无
备注: 无
\*******************************************************/
void Arithmetic::Operation(const std::string& left, const std::string& right, std::string& outcome, int& carry, int greater, int state, int plus)
{
	int i;
	char c;
	for (i = left.length()-1;i >= 0;--i)
	{
		int sum;
		if(state == 0 || greater == 0 && state == -1)
			sum = 0;
		if(greater == 1 && state == -1)
			sum = Atol(left[i]) - Atol(right[i]) + carry;
		if(greater == 2 && state == -1)
			sum = Atol(right[i]) - Atol(left[i]) + carry;
		if(state == 1 || greater == 0 && state == 1)
			sum = Atol(left[i]) + Atol(right[i]) + carry;
		if(i == 0 && plus == 1){}
		else
			SumCarry(sum, carry); 
		c = Itoa(sum);
		switch(c)
		{
		case 'A':
			outcome += "01";
			break;
		case 'B':
			outcome += "11";
			break;
		case 'C':
			outcome += "21";
			break;
		case 'D':
			outcome += "31";
			break;
		case 'E':
			outcome += "41";
			break;
		case 'F':
			outcome += "51";
			break;
		default:
			outcome += c;
		}
	}
}

/*******************************************************\
函数: Itoa
功能: 数字转字符
输入: 个位数
输出: 无
返回: 个位数字对应的字符
备注: 无
\*******************************************************/
char Arithmetic::Itoa(int n)
{
	char *a = "0123456789ABCDEF";
	return a[n - 0];
}

/*******************************************************\
函数: Multiply
功能: 计算大数乘法
输入: 无
输出: 无
返回: 积
备注: 重载的 * 中调用此函数
\*******************************************************/
std::string Arithmetic::Multiply(std::string left, std::string right, int digCount)
{
	using namespace std;
	Arithmetic sum = "0";
	int il;
	for (il = left.length() - 1;il >= 0;--il)
	{
		int ir, carry = 0;
		vector<string> strVector;
		std::string t = "";
		for (ir = right.length() - 1;ir >= 0;--ir)
		{
			char a[2], b[2];
			a[0] = left[il];
			b[0] = right[ir];
			a[1] = '\0';
			b[1] = '\0';
			std::string h;
			strVector.insert(strVector.end(), h = MulChar(a, b, carry));
		}
		if(carry != 0)
		{
			char c[3];
			itoa(carry, c, 10);
			strVector.insert(strVector.end(), c);
		}
		for(int i = strVector.size() - 1;i >= 0;--i)
			t += strVector[i];
		for (ir = left.length() - 1;ir != il;--ir)
			t += "0";
		Arithmetic str = t;
		sum = sum + str;
	}
	if(digCount >= sum.GetData().length())
	{
		int i = digCount - sum.GetData().length();
		std::string t = sum.GetData();
		while(i--)
			t.insert(0, "0");
		for (i = t.length()-1;t[i] == '0';--i)
			t.erase(i, 1);
		if(t != "")
			t.insert(0, "0.");
		else
			t = "0";
		sum = t;
	}
	else
	{
		std::string t = sum.GetData();
		t.insert(sum.GetData().length() - digCount, ".");
		for (int i = t.length()-1;t[i] == '0';--i)
			t.erase(i, 1);
		if(t[t.length()-1] == '.')
			t.erase(t.length()-1, 1);
		sum = t;
	}
	return sum.GetData();
}
/*******************************************************\
函数: MulChar
功能: 计算大数乘法
输入: 无
输出: 无
返回: 积
备注: 重载的 * 中 Multiply 中 调用此函数
\*******************************************************/
std::string Arithmetic::MulChar(char *a, char *b, int& carry)
{
	int t = atoi(a) * atoi(b) + carry;
	if(t >= 10)
	{
		carry = t / 10;
		t %= 10;
	}
	else
		carry = 0;
	char c[5];
	itoa(t, c, 10);
	std::string str = c;
	return str; 
}

/*******************************************************\
函数: Dividle
功能: 计算大数除法
输入: 无
输出: 无
返回: 商
备注: 重载的 / 中调用此函数
\*******************************************************/
std::string Arithmetic::Dividle(std::string numa, std::string numb, long m_precision)
{
	while(numb[0] == '0')
		numb.erase(0, 1);
	while(numa[0] == '0')
		numa.erase(0, 1);
	std::string result = "";
	int dig = 0;
	long ia = numa.length(), ib = numb.length(), nPrec = 0, lcarry = 0;
	if(ia < ib)//计算前确保字符串numa > numb
	{
		result = "0.";
		dig = 1;
		for (long i = 0;i < ib - ia;++i)
		{
			result += "0";
			numa += "0";
		}
		lcarry = numa.length();
		Arithmetic inuma = numa, inumb = numb, iresult = "";
		iresult = inuma - inumb;
		if(iresult.GetData()[0] == '-')
		{
//			result += "0";
			numa += "0";
//			++nPrec;
		}
		else
		{
			result.erase(result.length()-1, 1);
		}
	}
	else//计算前确保字符串numa > numb
	{
		if(ia == ib)
		{
			Arithmetic inuma = numa, inumb = numb, iresult = "";
			iresult = inuma - inumb;
			if(iresult.GetData()[0] == '-')
			{
				result = "0.";
				numa += "0";
				dig = 1;
				lcarry = numa.length();
			}
		}
		else
			lcarry = numa.length();
	}
	do
	{
		if(numa[0] == '0')//处理1000...类似的数据
		{
			while(numa[0] == '0')
			{
				numa.erase(0, 1);
				result += "0";
			}
		}
		if(numa.length() < ib)//每次运算前都会确保大于numb
		{
			ia = numa.length();
			if(dig == 0)
			{
				dig = 1;
				long i;
				for (i = 1;i < ia - lcarry;++i)
					result += "0";
				result += ".";
				for (i = ib - ia;i != 0;--i)
					numa += "0";
				for (i = ib - lcarry - 1;i != 0;--i)
					result += "0";
				Arithmetic inuma = numa, inumb = numb, iresult = "";
				iresult = inuma - inumb;
				lcarry = numa.length();
				if(iresult.GetData()[0] == '-')
				{
					numa += "0";
					result += "0";
				}
			}
			else
			{
				if(numa.length() == ib)
				{
					Arithmetic inuma = numa, inumb = numb, iresult = "";
					iresult = inuma - inumb;
					if(iresult.GetData()[0] == '-')
					{
						numa += "0";
						result += "0";
					}
				}
				else
				{
					long i = 0;
					for (i = ib - ia;i != 0;--i)
						numa += "0";
					for (i = ib - lcarry - 1;i != 0;--i)
						result += "0";
					Arithmetic inuma = numa, inumb = numb, iresult = "";
					iresult = inuma - inumb;
					lcarry = numa.length();
					if(iresult.GetData()[0] == '-')
					{
						numa += "0";
						result += "0";
					}
				}
			}
		}
		else
		{
			if(numa.length() == ib)
			{
				long ia = numa.length();
				Arithmetic inuma = numa, inumb = numb, iresult = "";
				iresult = inuma - inumb;
				if(iresult.GetData()[0] == '-')
				{
					if(dig == 0)
					{
						result += ".";
						dig = 1;
					}
					numa += "0";
//					result += "0";
				}
			}
		}
		std::string t = numa.substr(0, ib), carry = "";
		numa.erase(0, ib);
		Arithmetic inuma = t, inumb = numb, iresult = "";
		iresult = inuma - inumb;
		if(iresult.GetData()[0] == '-')
		{
			if(numa != "")////做10000 / 10 时,加上numa空字符串 numa[0]时会有意想不到的BUG,所以用了if
			{
				long i1 = t.length() - lcarry;
				for (long i = 0;i < i1;++i)
					result += "0";
				t += numa[0];
				numa.erase(0, 1);
			}
		}
		long count = 0;
		do
		{
			inuma = t;
			iresult = inuma - inumb;
			if(iresult.GetData()[0] != '-')
			{
				t = iresult.GetData();
				++count;
			}
		}while(iresult.GetData()[0] != '-');
		while(t[0] == '0')
			t.erase(0, 1);
		if(t == "")
			t = "0";
		carry = t;
		char *pc = new char[15];
		itoa(count, pc, 10);
//		if(result == "1400657190290894403272006596")
//			std::cout << result << std::endl;
		if(strcmp(pc, "0"))
			result += pc;
		delete [] pc;
		if(carry != "0" && carry != "")
			numa.insert(0, carry);
		lcarry = carry.length();
		if(carry == "" || carry == "0")
			lcarry = 0;
		if(result.find(".") < result.length())
			nPrec = result.length()-1 - result.find(".");
	}while(numa != "" && nPrec <= m_precision+1); 

	if(result.find(".") < result.length())
	{
		while(result[result.length()-1] == '0')
			result.erase(result.length()-1, 1);
	}
	else
	{
		if(result != "0")
		{
			while(result[0] == '0')
				result.erase(0, 1);
		}
	}
	if(result[result.length()-1] == '.')
		result.erase(result.length()-1, 1);
	if(result.find(".") < result.length())
	{
		if(result.length() - result.find(".") > m_precision+1)
		{
			for (long i = result.find(".")+1;result[i] == '0';++i);
			if(i < result.find(".")+1 + m_precision+1)
				result.erase(result.find(".") + m_precision+2, result.length());
		}
	}

	return result;
}

/*******************************************************\
函数: PlusMinus
功能: 计算大数加减法
输入: 无
输出: 无
返回: 和或差
备注: 加减法通用,减法时需将被减数加1负号再调用此函数
\*******************************************************/
std::string Arithmetic::PlusMinus(std::string &left, std::string &right)
{
	std::string tInteger = "0", tDigits = "0";
	std::string ledigits = "0", ridigits = "0";
	std::string result = "";
	int state, lsign = 1, rsign = 1, greater, i, carry = 0, plus;
	if(left[0] == '-')
	{
		left.erase(0, 1);
		lsign = -1;
	}
	if(right[0] == '-')
	{
		right.erase(0, 1);
		rsign = -1;
	}
	if((i = left.find('.')) < left.length())
	{
		ledigits = left.substr(i+1, left.length() - i - 1);
		left.erase(i, left.length() - i);
	}
	if((i = right.find('.')) < right.length())
	{
		ridigits = right.substr(i+1, right.length() - i - 1);
		right.erase(i, right.length() - i);
	}
	StringInsert(left, right, 1);//填充0,使长度相等
	StringInsert(ledigits, ridigits, 2);//填充0,使长度相等
	greater = Compare(left, right);
	if(greater == 0)
		greater = Compare(ledigits, ridigits);
	state = lsign == rsign ? lsign : greater == 0 ? 0 : greater == 1 ? lsign : rsign; 
	plus = lsign == rsign ? 1 : -1;
	Operation(ledigits, ridigits, tDigits, carry, greater, plus, 0);
	Operation(left, right, tInteger, carry, greater, plus, 1);
	tInteger.erase(0, 1);
	tDigits.erase(0, 1);
	std::reverse(tInteger.begin(), tInteger.end());
	for (i = 0;i < tInteger.length() && tInteger[i] == '0';++i);
	tInteger.erase(0, i);
	for (i = 0;i < tDigits.length() && tDigits[i] == '0';++i);
	tDigits.erase(0, i);
	std::reverse(tDigits.begin(), tDigits.end());
	if(tInteger == "\0" && tDigits != "\0")
	{
		if(state == -1)
			result += "-";
		result = result + "0" + "." + tDigits;
	}
	if(tInteger != "\0" && tDigits != "\0")
	{
		if(state == -1)
			result += "-";
		result = result + tInteger + "." + tDigits;
	}
	if(tInteger != "\0" && tDigits == "\0")
	{
		if(state == -1)
			result += "-";
		result = result + tInteger;
	}
	if(tInteger == "\0" && tDigits == "\0")
		result += "0";
	return result;
}

/*******************************************************\
函数: StringInsert
功能: 填充0,使长度相等
输入: 无
输出: 无
返回: 无
备注:ntype = 1代表填充整数部分,2代表填充小数部分
\*******************************************************/
void Arithmetic::StringInsert(std::string& left, std::string& right, int ntype)
{
	std::string t;
	int i;
	for (i = abs((int)left.length() - (int)right.length());i > 0;--i)
		t += "0";
	if(left.length() > right.length() && ntype == 1)
		right.insert(0, t);
	if(left.length() < right.length() && ntype == 1)
		left.insert(0, t);
	if(left.length() > right.length() && ntype == 2)
		right.insert(right.length(), t);
	if(left.length() < right.length() && ntype == 2)
		left.insert(left.length(), t);
}

/*******************************************************\
函数: GetData()
功能: 获取类成员
输入: 无
输出: 无
返回: m_num
\*******************************************************/
std::string Arithmetic::GetData() const
{
	return m_num;
}

/*******************************************************\
函数: operator + 
功能: 计算大数加法
输入: Arithmetic对象
输出: 无
返回: 2数之和
\*******************************************************/
Arithmetic operator + (Arithmetic& numa, Arithmetic& numb)
{
	std::string strNuma = numa.GetData(), strNumb = numb.GetData();
	Arithmetic result = numa.PlusMinus(strNuma, strNumb);
	return result;
}

/*******************************************************\
函数: operator - 
功能: 计算大数减法
输入: Arithmetic对象
输出: 无
返回: 2数之差

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -