可以计算阶乘次方的大数计算器

昨天突然想写个计算器,支持无限位数结果的。于是乎就写了个...现在把写的过程记录下来,供大家互相学习!

首先,要做计算,我首先想到的就是逆波兰


百度查到的定义是

//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一个 表达式E的后缀形式可以如下定义:
(1)如果E是一个变量或 常量,则E的 后缀式是E本身。
(2)如果E是E1 op E2形式的表达式,这里op是如何二元操作符,则E的后缀式为E1'E2' op,这里E1'和E2'分别为E1和E2的后缀式。
(3)如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。
如:我们平时写a+b,这是中缀表达式,写成 后缀表达式就是:ab+
(a+b)*c-(a+b)/e的后缀表达式为:
(a+b)*c-(a+b)/e
→((a+b)*c)((a+b)/e)-
→((a+b)c*)((a+b)e/)-
→(ab+c*)(ab+e/)-
→ab+c*ab+e/-
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

我的理解是:

把表达式看作符号和数字组成的字符串

如果是数字,就放到一个容器里,如果是符号则放到另一个容器里,然后根据逆波兰的规则,把符号容器里的符号依次提到存数字字符串的容器中,这样就能转换

比如:

(a+b)*c-(a+b)/e

1 存数字的容器:

1 存运算符的容器:(

2 存数字的容器:a

2 存

运算符
的容器:(

3 存数字的容器:a

3 存运算符的容器:(+

4 存数字的容器:ab

4 存

运算符
的容器:(+

5 存数字的容器:ab+
5 存运算符的容器:
6 存数字的容器:ab+
6 存 运算符的容器:*
7 存数字的容器:ab+c
7 存 运算符的容器:*
8 存数字的容器:ab+c*
8 存运算符的容器:-
9 存数字的容器:ab+c*
9 存运算符的容器:-(
10 存数字的容器:ab+c*a
10 存运算符的容器:-(
11 存数字的容器:ab+c*a
11 存运算符的容器:-(+
12 存数字的容器:ab+c*ab
12 存运算符的容器:-(+
13 存数字的容器:ab+c*ab+
13 存运算符的容器:-
14 存数字的容器:ab+c*ab+
14 存运算符的容器:-/
15 存数字的容器:ab+c*ab+e
15 存运算符的容器:-/
16 存数字的容器:ab+c*ab+e/
16 存运算符的容器:-
17 存数字的容器:ab+c*ab+e/-
17 存运算符的容器:
要注意以下几点:
1.要放入存运算符的容器前 先判断下优先级 如果要放入的运算符比前面的符号优先级低,则先将前面的运算符取出放到存数字的容器中 再放入运算符
2.遇到右括号 则直接把前面到左括号之前的运算符都依次取出放入存数字的容器,左括号直接丢弃
3.如果后面已经没有字符了,而存运算符的容器里面还有字符,则依次取出放入存数字的容器
4.如果有连续两个- 则将前面一个-改为+ 
5.如果左括号前面没有 + - * / ( ^! 等运算符 则 在前面补个*
6.如果-是在第一个字符或者 - 前面是( 则这个-代表负数 可以用'#'来代表
//-----------------------------------------------------------------------------------------------------------------------------------------------------
当成功转成逆波兰算式以后,要计算起来就比较简单了。 我先写了个 直接转成double型的来做下实验。
在遇到字符的时候,如果是+-*/^其中之一 则取出前面两个数 a b, 进行 a 操作符 b 求出结果,然后把a b 取出 把结果存入,如果是!则只取前面一个数进行!a得出结果,把a取出,把结果存入,这样 最后就会得出一个结果,这个就是我们要求出的值了!
代码如下:
<pre name="code" class="cpp">
#include<iostream>
#include<vector>
#include<string>
#include<cstdio>

using namespace std;

#define LIFE '('
#define RIGHT ')'
#define THEPOW '^'
#define JIECHENG '!'
#define MUL '*'
#define DIV '/'
#define ADD '+'
#define SUB '-'

class calculator
{
private:
	string import; //输入
	string outport; //输出
	vector<string> res_import; //转换后的输入

public:
	calculator();
	~calculator();
	//输入 
	bool PutIn();
	//将输入的公式转换成逆波兰形式存储到vector
	bool Change();
	//得到结果
	void GetResult();
	//输出
	void PutOut();

	//计算
	string DoCalculator(const string &a, const string &b, const char &fuhao);

	//优先级判断 是否低于前面
	bool IsLow(const char &a, const char &b);
	//优先级计算
	int FirstCode(const char &a);

};

calculator::calculator() :import(""), outport(""), res_import(NULL)
{

}
calculator::~calculator()
{

}
bool calculator::PutIn()
{
	import = "";
	getline(cin, import);
	if (import == "")
		return false;
	else
		return true;
}
bool calculator::Change()
{
	vector<string> temp; //用来临时存储操作符号的
	string temp_str = ""; //用来临时存储数字

	for (int i = 0; i < import.size(); i++)
	{
		string temp_fh = "";
		//数字
		if ((import[i] >= '0' && import[i] <= '9') || import[i] == '.')
		{
			temp_str.push_back(import[i]);
		}
		else if (import[i] == LIFE)
		{
			if (i > 0 && import[i - 1] != LIFE && import[i - 1] != THEPOW && import[i - 1] && JIECHENG && import[i - 1] != MUL && import[i - 1] != DIV && import[i - 1] != ADD && import[i - 1] != SUB)
			{
				if (temp_str != "")
				{
					res_import.push_back(temp_str);
					temp_str = "";
				}
				temp.push_back("*");
			}
			temp_fh = import[i];
			temp.push_back(temp_fh);
		}
		else if (import[i] == RIGHT)
		{
			//把整个数字压入
			if (temp_str != "")
			{
				res_import.push_back(temp_str);
				temp_str = "";
			}
			//弹出括号里面的符号
			if (temp.size() > 0)
			{
				string fuhao = temp.at(temp.size() - 1);
				while (fuhao[0] != LIFE)
				{
					temp.pop_back();
					res_import.push_back(fuhao);
					if (temp.size() <= 0)
						break;
					fuhao = temp.at(temp.size() - 1);
				}

				//弹出左括号
				temp.pop_back();
			}
		}
		else if (import[i] == THEPOW || import[i] == JIECHENG || import[i] == MUL || import[i] == DIV || import[i] == ADD || import[i] == SUB)
		{
			//把整个数字压入
			if (temp_str != "")
			{
				res_import.push_back(temp_str);
				temp_str = "";
			}
			//判断优先级 如果比前面的低 则弹出前面一个
			if (temp.size() > 0)
			{
				string fuhao = temp.at(temp.size() - 1); //前一个
				while (IsLow(import[i], fuhao[0]))
				{
					temp.pop_back();
					if (fuhao[0] == SUB && res_import.at(res_import.size() - 1)[0] == SUB)
					{
						res_import.at(res_import.size() - 1)[0] = '+';
					}
					res_import.push_back(fuhao);
					if (temp.size() <= 0)
						break;
					fuhao = temp.at(temp.size() - 1);
				}
			}
			//压入这个符号
			temp_fh = import[i];
			temp.push_back(temp_fh);
		}
	}
	//把整个数字压入 用于最后一个字符是数字的情况
	if (temp_str != "")
	{
		res_import.push_back(temp_str);
		temp_str = "";
	}
	//将符号全部取出
	for (; temp.size() > 0;)
	{
		string fuhao = temp.at(temp.size() - 1); 
		temp.pop_back();
		if (fuhao[0] == SUB && res_import.at(res_import.size() - 1)[0] == SUB)
		{
			res_import.at(res_import.size() - 1)[0] = '+';
		}
		res_import.push_back(fuhao);
		if (temp.size() <= 0)
			break;
		fuhao = temp.at(temp.size() - 1);
	}
	//转换成功与否
	if (res_import.size() > 0)
		return true;
	else
		return false;
}
void calculator::PutOut()
{
	cout << "计算结果为:" << outport.c_str() << endl;
}
bool calculator::IsLow(const char &a, const char &b)
{
	if (FirstCode(a) < FirstCode(b))
		return true;
	else
		return false;
}
int calculator::FirstCode(const char &a)
{
	switch (a)
	{
	case LIFE:
	case RIGHT:
		return 0;
	case THEPOW:
		return 9;
	case JIECHENG:
		return 8;
	case MUL:
		return 5;
	case DIV:
		return 6;
	case ADD:
		return 2;
	case SUB:
		return 3;
	}
	return 0;
}
void calculator::GetResult()
{
	outport = "";
	vector<string> temp; //用于临时计算结果用的栈
	string temp_str = "";//临时存储数字
	for (int i = 0; i < res_import.size(); i++)
	{
		if (res_import[i][0] == JIECHENG)  //如果是阶乘 则只需要一元
		{
			if (temp.size() < 1)
				return ;
			string res = DoCalculator(temp[temp.size() - 1], "", res_import[i][0]);
			if (res == "")
				return ;
			temp.pop_back();	 //弹出上一个数字
			temp.push_back(res); //压入计算后的结果
		}
		else if (res_import[i][0] == THEPOW || res_import[i][0] == MUL || res_import[i][0] == DIV || res_import[i][0] == ADD || res_import[i][0] == SUB)
		{
			if (temp.size() < 2)
				return ;
			string res = DoCalculator(temp[temp.size() - 2], temp[temp.size() - 1], res_import[i][0]);
			if (res == "")
				return ;
			temp.pop_back();    //弹出上一个数字
			temp.pop_back();    //弹出上一个数字
			temp.push_back(res);//压入计算后的结果
		}
		else  //数字
		{
			//直接压入临时栈
			temp.push_back(res_import[i]);
		}
	}

	outport = temp[0];
	return ;
}
string calculator::DoCalculator(const string &a, const string &b, const char &fuhao)
{
	double the_res = 0;
	switch (fuhao)
	{
	case JIECHENG:
		break;
	case THEPOW:
		the_res = pow(atof(a.c_str()), atof(b.c_str()));
		break;
	case MUL:
		the_res = atof(a.c_str())*atof(b.c_str());
		break;
	case DIV:
		the_res = atof(a.c_str()) / atof(b.c_str());
		break;
	case ADD:
		the_res = atof(a.c_str()) + atof(b.c_str());
		break;
	case SUB:
		the_res = atof(a.c_str()) - atof(b.c_str());
		break;
	}

	char buffer[1024];
	sprintf_s(buffer, "%f\0", the_res);
	string str(buffer);

	return str;
}

int main()
{
	calculator cal;
	cout << "请输入公式:" << endl;
	while (!cal.PutIn() || !cal.Change())
	{
		cout << "输入有误,请重新输入" << endl;
	}

	cal.GetResult();
	cal.PutOut();

	system("pause");
	return 0;
}
</pre>

 附上运行结果截图: 
 
以上就是做出普通计算器的过程(截至此仅为测试 所以我没有写上阶乘的循环,如果仅需要在double型范围内 则可自行补充即可使用)
前面我说了,我要做的是支持大数计算的,所以,接下去我们要稍作修改,把计算改为字符串类型的计算,这样就可以了。
思路:
我们可以想想我们用笔算的时候,是如何计算出加减乘除的。
加法:对齐小数点,小数部分先相加,从最后一位开始加起,如果超过进制,就向前进1,逐位计算。
换成大数计算的话,我们可以不必每一个数字为一位,我们可以多个数字为一位,如4个数字为一位,就是10000进制。所以我们可以先对字符串进行处理。将整数部分的前面补0对齐,小数部分的后面补0对齐,然后分割成每4位数为一个int的vector,这样就可以跟笔算一样计算下去,多少位都不怕!当然 要先判断正负号。如果一负一正 则转换为减法。如果两个都是负数 则得数前面要加-号。
减法:同理,减法也是要先对齐。不过 有个地方要注意,正负号取出,先判断两个数都为正的时候谁比较大,都是用比较大的数去减小的数。最后再去判断正负号的问题。减法也是一位位计算,如果不够减了,就向前面一位借1,以此类推。
乘法:每位循环相乘,结果相加。就跟我们笔算一样的概念。做出加法以后 乘法就很简单了。就不详细写了。记住负负得正 正负得负。
除法:除法比较难。按最简单暴力的方法,就是将有小数的数字转换为整数。然后用除数一直去减被除数。直到得数为0。这个是可以解决任意两个数相除的,但是有个问题,就是如果是除以1 那么要循环N次减法 这样效率就坑爹了。于是 我们先进行一个判断,先判断被除数有没有大于9位数。如果没有的话,我们可以将除数每9位分割,然后分别去除再相加。我们1234/5678 其实 等于 (1/5678) * 10^3+(2/5678) * 10^2+(3/5678) * 10^1+(4/5678) * 10^0 这样,就可以较快的计算了。
至于阶乘次方这些 基本的加减乘除出来以后,就迎刃而解了!
总结,需要注意以下几点:
1.小数部分和整数部分需要分开
2.正负号在处理数字之前判断,所有计算 都整理为正数进行计算会好些
3.不要使用每一个字符为一位进行计算!效率低得可怕!
4.该补0的要注意补0
5.位数分割要合理,我这边是以每4个字符为一位来处理,因为我用的vector<int>来处理,如果用64位的 则可以设置大点
代码如下:
#include<iostream>
#include<vector>
#include<string>
#include<cstdio>
#include<ctime>

using namespace std;

#define LEFT '('
#define RIGHT ')'
#define THPOWER '^'
#define FACTORIAL '!' 
#define MUL '*'
#define DIV '/'
#define ADD '+'
#define SUB '-'
#define MINUS '#' 
#define DIGIT 4 
#define ARY 10000 

//计算器类
class calculator
{
private:
	string import; //输入
	string outport; //输出
	vector<string> res_import; //转换后的输入

public:
	calculator();
	~calculator();
	//输入 
	bool PutIn();
	//将输入的公式转换成逆波兰形式存储到vector
	bool Change();
	//得到结果
	void GetResult();
	//输出
	void PutOut();

	//计算
	string DoCalculator(const string &a, const string &b, const char &fuhao);

	//优先级判断 是否低于前面
	bool IsLow(const char &a, const char &b);
	//优先级计算
	int FirstCode(const char &a);
	//字符串分成整数和小数部分
	void DoCalBase(const string &a, const string &b, vector<int> &int_a_i, vector<int> &int_b_i, vector<int> &int_a_f, vector<int> &int_b_f);
	//字符串对其补0 
	void DoToAlign(vector<int> &int_a_i, vector<int> &int_b_i, vector<int> &int_a_f, vector<int> &int_b_f);
	//字符串去掉.
	void DoToDelPoint(int &n, const string &a, const string &b, vector<int> &int_a_i, vector<int> &int_b_i);
	//去掉前面的0
	void DoDelFront(string &a);
	//去掉后面的0
	void DoDelBack(string &a);
	//将两个数字都化为整数(给除法用)
	void DoToBeInt(const string &a, const string &b, string &str_a_i, string &str_b_i);
	//加
	string DoAdd(const string &a, const string &b);
	//减
	string DoSub(const string &a, const string &b);
	//乘
	string DoMul(const string &a, const string &b);
	//除
	string DoDiv(const string &a, const string &b);
	//次方
	string DoTHPOWER(const string &a, const string &b);
	//阶乘
	string DoFACTORIAL(const string &a);
	//负号
	string DoNegativeNumber(const string &a);
};

calculator::calculator() :import(""), outport(""), res_import(NULL)
{

}
calculator::~calculator()
{

}
bool calculator::PutIn()
{
	import = "";
	getline(cin, import);
	if (import == "")
		return false;
	else
		return true;
}
bool calculator::Change()
{
	vector<string> temp; //用来临时存储操作符号的
	string temp_str = ""; //用来临时存储数字

	for (int i = 0; i < import.size(); i++)
	{
		string temp_minus = "";
		//数字
		if ((import[i] >= '0' && import[i] <= '9') || import[i] == '.')
		{
			temp_str.push_back(import[i]);
		}
		else if (import[i] == LEFT)
		{
			if (i > 0 && import[i - 1] != LEFT && import[i - 1] != THPOWER && import[i - 1] && FACTORIAL && import[i - 1] != MUL && import[i - 1] != DIV && import[i - 1] != ADD && import[i - 1] != SUB && import[i - 1] != MINUS)
			{
				if (temp_str != "")
				{
					res_import.push_back(temp_str);
					temp_str = "";
				}
				temp.push_back("*");
			}
			temp_minus = import[i];
			temp.push_back(temp_minus);
		}
		else if (import[i] == RIGHT)
		{
			//把整个数字压入
			if (temp_str != "")
			{
				res_import.push_back(temp_str);
				temp_str = "";
			}
			//弹出括号里面的符号
			if (temp.size() > 0)
			{
				string fuhao = temp.at(temp.size() - 1);
				while (fuhao[0] != LEFT)
				{
					temp.pop_back();
					res_import.push_back(fuhao);
					if (temp.size() <= 0)
						break;
					fuhao = temp.at(temp.size() - 1);
				}

				//弹出左括号
				temp.pop_back();
			}
		}
		else if (import[i] == THPOWER || import[i] == FACTORIAL || import[i] == MUL || import[i] == DIV || import[i] == ADD || import[i] == SUB || import[i] == MINUS)
		{
			//把整个数字压入
			if (temp_str != "")
			{
				res_import.push_back(temp_str);
				temp_str = "";
			}
			//如果是负数 则特殊处理
			if (import[i] == SUB)
			{
				if (i == 0 || import[i - 1] == LEFT ||  import[i - 1] == ADD ||  import[i - 1] == SUB ||  import[i - 1] == MUL ||  import[i - 1] == DIV ||  import[i - 1] == THPOWER ||  import[i - 1] == FACTORIAL ||  import[i - 1] == MINUS )
				{
					//压入#代表负数符号
					import[i] = MINUS;
				}
			}
			//判断优先级 如果比前面的低 则弹出前面一个
			if (temp.size() > 0)
			{
				string fuhao = temp.at(temp.size() - 1); //前一个
				while (IsLow(import[i], fuhao[0]))
				{
					temp.pop_back();
					if (fuhao[0] == SUB && res_import.at(res_import.size() - 1)[0] == SUB)
					{
						res_import.at(res_import.size() - 1)[0] = '+';
					}
					res_import.push_back(fuhao);
					if (temp.size() <= 0)
						break;
					fuhao = temp.at(temp.size() - 1);
				}
			}
			//压入这个符号
			temp_minus = import[i];
			temp.push_back(temp_minus);
		}
	}
	//把整个数字压入 用于最后一个字符是数字的情况
	if (temp_str != "")
	{
		res_import.push_back(temp_str);
		temp_str = "";
	}
	//将符号全部取出
	for (; temp.size() > 0;)
	{
		string fuhao = temp.at(temp.size() - 1); 
		temp.pop_back();
		if (fuhao[0] == SUB && res_import.at(res_import.size() - 1)[0] == SUB)
		{
			res_import.at(res_import.size() - 1)[0] = '+';
		}
		res_import.push_back(fuhao);
		if (temp.size() <= 0)
			break;
		fuhao = temp.at(temp.size() - 1);
	}
	//转换成功与否
	if (res_import.size() > 0)
		return true;
	else
		return false;
}
void calculator::PutOut()
{
	cout << "计算结果为:" << outport.c_str() << endl;
}
bool calculator::IsLow(const char &a, const char &b)
{
	if (FirstCode(a) < FirstCode(b))
		return true;
	else
		return false;
}
int calculator::FirstCode(const char &a)
{
	switch (a)
	{
	case LEFT:
	case RIGHT:
		return 0;
	case THPOWER:
		return 9;
	case FACTORIAL:
		return 8;
	case MUL:
		return 5;
	case DIV:
		return 6;
	case ADD:
		return 2;
	case SUB:
		return 3;
	case MINUS:
		return 9;
	}
	return 0;
}
void calculator::GetResult()
{
	outport = "";
	vector<string> temp; //用于临时计算结果用的栈
	string temp_str = "";//临时存储数字
	for (int i = 0; i < res_import.size(); i++)
	{
		if (res_import[i][0] == FACTORIAL || res_import[i][0] == MINUS )  //如果是阶乘或者符号 则只需要一元
		{
			if (temp.size() < 1)
				return ;
			string res = DoCalculator(temp[temp.size() - 1], "", res_import[i][0]);
			if (res == "")
				return ;
			temp.pop_back();	 //弹出上一个数字
			temp.push_back(res); //压入计算后的结果
		}
		else if (res_import[i].size() == 1 && (res_import[i][0] == THPOWER || res_import[i][0] == MUL || res_import[i][0] == DIV || res_import[i][0] == ADD || res_import[i][0] == SUB))
		{
			if (temp.size() < 2)
				return ;
			string res = DoCalculator(temp[temp.size() - 2], temp[temp.size() - 1], res_import[i][0]);
			if (res == "")
				return ;
			temp.pop_back();    //弹出上一个数字
			temp.pop_back();    //弹出上一个数字
			temp.push_back(res);//压入计算后的结果
		}
		else  //数字
		{
			//直接压入临时栈
			temp.push_back(res_import[i]);
		}
	}

	outport = temp[0];
	return ;
}
string calculator::DoCalculator(const string &a, const string &b, const char &fuhao)
{
	string the_res = "";
	switch (fuhao)
	{
	case MINUS:
		the_res = DoNegativeNumber(a);
		break;
	case FACTORIAL:
		the_res = DoFACTORIAL(a);
		break;
	case THPOWER:
		the_res = DoTHPOWER(a,b);
		break;
	case MUL:
		the_res = DoMul(a, b);
		break;
	case DIV:
		the_res = DoDiv(a, b);
		break;
	case ADD:
		the_res = DoAdd(a, b);
		break;
	case SUB:
		the_res = DoSub(a, b);
		break;
	}
	return the_res;
}
void calculator::DoCalBase(const string &a, const string &b, vector<int> &int_a_i, vector<int> &int_b_i, vector<int> &int_a_f, vector<int> &int_b_f)
{
	string str_a_i = "";
	string str_b_i = "";
	string str_a_f = "";
	string str_b_f = "";

	int_a_i.clear();
	int_b_i.clear();
	int_a_f.clear();
	int_b_f.clear();

	//把数字的整数和小数部分分别分割
	bool is_i = true;
	for (int i = 0; i < a.size(); i++)
	{
		if (a[i] == '-')
			continue;
		if (a[i] == '.')
		{
			is_i = false;
			continue;
		}
		if (is_i)
		{
			str_a_i += a[i];
		}
		else
		{
			str_a_f += a[i];
		}
	}
	is_i = true;
	for (int i = 0; i < b.size(); i++)
	{
		if (b[i] == '-')
			continue;
		if (b[i] == '.')
		{
			is_i = false;
			continue;
		}
		if (is_i)
		{
			str_b_i += b[i];
		}
		else
		{
			str_b_f += b[i];
		}
	}

	//将小数部分对齐 
	DoDelBack(str_a_f);
	DoDelBack(str_b_f);
	int f_max = str_a_f.size() - str_b_f.size();
	if (f_max > 0)
	{
		for (int i = 0; i < f_max; i++)
		{
			str_b_f = str_b_f + "0";
		}
	}
	else if (f_max < 0)
	{
		f_max = -f_max;
		for (int i = 0; i < f_max; i++)
		{
			str_a_f = str_a_f + "0";
		}
	}
	int bunumber = str_a_f.size() % DIGIT;
	if (bunumber > 0)
	{
		for (int i = 0; i < DIGIT - bunumber; i++)
		{
			str_a_f = str_a_f + "0";
			str_b_f = str_b_f + "0";
		}
	}
	//每N位分割
	int number = str_a_i.size() / DIGIT + 1; //多少个元素
	int count = str_a_i.size() % DIGIT;  //第一个元素有多少个字符
	string str_temp = "";
	int now_count = 0;
	for (; now_count < count; now_count++)
	{
		str_temp = str_temp + str_a_i[now_count];
	}

	if (str_temp != "")
	{
		int_a_i.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}

	for (int j = 1; j < number; j++)
	{
		bool is_push = false;
		for (int i = 0; i < DIGIT; i++, now_count++)
		{
			if (str_a_i[now_count] != '0')
				is_push = true;
			if (is_push)
				str_temp = str_temp + str_a_i[now_count];
		}
		if (str_temp == "")
			str_temp = "0";
		int_a_i.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}

	number = str_b_i.size() / DIGIT + 1; //多少个元素
	count = str_b_i.size() % DIGIT;  //第一个元素有多少个字符
	str_temp = "";
	now_count = 0;
	for (; now_count < count; now_count++)
	{
		str_temp = str_temp + str_b_i[now_count];
	}
	if (str_temp != "")
	{
		int_b_i.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}

	for (int j = 1; j < number; j++)
	{
		bool is_push = false;
		for (int i = 0; i < DIGIT; i++, now_count++)
		{
			if (str_b_i[now_count] != '0')
				is_push = true;
			if (is_push)
				str_temp = str_temp + str_b_i[now_count];
		}
		if (str_temp == "")
			str_temp = "0";
		int_b_i.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}

	//f
	number = str_a_f.size() / DIGIT + 1; //多少个元素
	count = str_a_f.size() % DIGIT;  //第一个元素有多少个字符
	str_temp = "";
	now_count = 0;
	for (; now_count < count; now_count++)
	{
		str_temp = str_temp + str_a_f[now_count];
	}
	if (str_temp != "")
	{
		int_a_f.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}

	for (int j = 1; j < number; j++)
	{
		bool is_push = false;
		for (int i = 0; i < DIGIT; i++, now_count++)
		{
			if (str_a_f[now_count] != '0')
				is_push = true;
			if (is_push)
				str_temp = str_temp + str_a_f[now_count];
		}
		if (str_temp == "")
			str_temp = "0";
		int_a_f.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}

	number = str_b_f.size() / DIGIT + 1; //多少个元素
	count = str_b_f.size() % DIGIT;  //第一个元素有多少个字符
	str_temp = "";
	now_count = 0;
	for (; now_count < count; now_count++)
	{
		str_temp = str_temp + str_b_f[now_count];
	}
	if (str_temp != "")
	{
		int_b_f.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}

	for (int j = 1; j < number; j++)
	{
		bool is_push = false;
		for (int i = 0; i < DIGIT; i++, now_count++)
		{
			if (str_b_f[now_count] != '0')
				is_push = true;
			if (is_push)
				str_temp = str_temp + str_b_f[now_count];
		}
		if (str_temp == "")
			str_temp = "0";
		int_b_f.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}
}
//字符串对其补0
void calculator::DoToAlign(vector<int> &int_a_i, vector<int> &int_b_i, vector<int> &int_a_f, vector<int> &int_b_f)
{
	int i_max = int_a_i.size() - int_b_i.size();
	if (i_max > 0)
	{
		for (int i = 0; i < i_max; i++)
		{
			int_b_i.insert(int_b_i.begin(), 0);
		}
	}
	else if (i_max < 0)
	{
		i_max = -i_max;
		for (int i = 0; i < i_max; i++)
		{
			int_a_i.insert(int_a_i.begin(), 0);
		}
	}

	int f_max = int_a_f.size() - int_b_f.size();
	if (f_max > 0)
	{
		for (int i = 0; i < f_max; i++)
		{
			int_b_f.push_back(0);
		}
	}
	else if (f_max < 0)
	{
		f_max = -f_max;
		for (int i = 0; i < f_max; i++)
		{
			int_a_f.push_back(0);
		}
	}
}
//去掉小数点 记录以后小数点要在倒数第几个
void calculator::DoToDelPoint(int &n, const string &a, const string &b, vector<int> &int_a_i, vector<int> &int_b_i)
{
	n = 0;
	string str_a_i = "";
	string str_b_i = "";

	int_a_i.clear();
	int_b_i.clear();

	bool is_dian = false;
	for (int i = 0; i < a.size(); i++)
	{
		if (a[i] == '.')
		{
			is_dian = true;
			continue;
		}
		if (is_dian)
			n++;

		str_a_i += a[i];
	}

	is_dian = false;
	for (int i = 0; i < b.size(); i++)
	{
		if (b[i] == '.')
		{
			is_dian = true;
			continue;
		}
		if (is_dian)
			n++;

		str_b_i += b[i];
	}
	DoDelFront(str_a_i);
	DoDelFront(str_b_i);
	//每N位分割
	int number = str_a_i.size() / DIGIT + 1; //多少个元素
	int count = str_a_i.size() % DIGIT;  //第一个元素有多少个字符
	string str_temp = "";
	int now_count = 0;
	for (; now_count < count; now_count++)
	{
		str_temp = str_temp + str_a_i[now_count];
	}

	if (str_temp != "")
	{
		int_a_i.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}

	for (int j = 1; j < number; j++)
	{
		bool is_push = false;
		for (int i = 0; i < DIGIT; i++, now_count++)
		{
			if (str_a_i[now_count] != '0')
				is_push = true;
			if (is_push)
				str_temp = str_temp + str_a_i[now_count];
		}
		if (str_temp == "")
			str_temp = "0";
		int_a_i.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}

	number = str_b_i.size() / DIGIT + 1; //多少个元素
	count = str_b_i.size() % DIGIT;  //第一个元素有多少个字符
	str_temp = "";
	now_count = 0;
	for (; now_count < count; now_count++)
	{
		str_temp = str_temp + str_b_i[now_count];
	}

	if (str_temp != "")
	{
		int_b_i.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}

	for (int j = 1; j < number; j++)
	{
		bool is_push = false;
		for (int i = 0; i < DIGIT; i++, now_count++)
		{
			if (str_b_i[now_count] != '0')
				is_push = true;
			if (is_push)
				str_temp = str_temp + str_b_i[now_count];
		}
		if (str_temp == "")
			str_temp = "0";
		int_b_i.push_back(atoi(str_temp.c_str()));
		str_temp = "";
	}
}
//给除法用
void calculator::DoToBeInt(const string &a, const string &b, string &str_a_i, string &str_b_i)
{
	int n1 = 0;
	int n2 = 0;
	str_a_i = "";
	str_b_i = "";

	bool is_dian = false;
	for (int i = 0; i < a.size(); i++)
	{
		if (a[i] == '.')
		{
			is_dian = true;
			continue;
		}
		if (is_dian)
			n1++;

		str_a_i += a[i];
	}

	is_dian = false;
	for (int i = 0; i < b.size(); i++)
	{
		if (b[i] == '.')
		{
			is_dian = true;
			continue;
		}
		if (is_dian)
			n2++;

		str_b_i += b[i];
	}
	DoDelFront(str_a_i);
	DoDelFront(str_b_i);

	//
	int n = n1 - n2;
	if(n > 0)
	{
		for(int i = 0; i < n; i++)
		{
			str_b_i.push_back('0');
		}
	}
	else if(n < 0)
	{
		for(int i = 0; i < -n; i++)
		{
			str_a_i.push_back('0');
		}
	}
	if(	str_a_i == "")
		str_a_i = "0";
	if(	str_b_i == "")
		str_b_i = "0";
}
//去掉前面的0
void calculator::DoDelFront(string &a)
{
	if (a.size() <= 0)
		return;
	while (a[0] == '0')
	{
		a.erase(a.begin());

		if (a.size() <= 0)
			return;
	}
}
//去掉后面的0
void calculator::DoDelBack(string &a)
{
	if (a.size() <= 0)
		return;
	while (a[a.size()-1] == '0')
	{
		a.erase(a.end() - 1);

		if (a.size() <= 0)
			return;
	}
}
//加法
string calculator::DoAdd(const string &a, const string &b)
{
	string f_str = "";
	string i_str = "";
	string is_fushu = "";

	vector<int> int_a_i; //a整数部分
	vector<int> int_a_f; //a小数部分
	vector<int> int_b_i; //b整数部分
	vector<int> int_b_f; //b小数部分

	string aa = a;
	string bb = b;
	if (a[0] == '-')
		aa.erase(aa.begin());
	if (b[0] == '-')
		bb.erase(bb.begin());

	if (a[0] == '-')
	{
		if (b[0] == '-')
		{
			is_fushu = "-";
		}
		else
		{
			return DoSub(bb, aa);
		}
	}
	else
	{
		if (b[0] == '-')
		{
			return DoSub(aa, bb);
		}
	}

	DoCalBase(aa, bb, int_a_i, int_b_i, int_a_f, int_b_f);
	DoToAlign(int_a_i, int_b_i, int_a_f, int_b_f);

	//每N位分别相加
	int temp = 0; //进位的数
	for (int i = int_a_f.size() - 1; i >= 0; i--)
	{
		int res = int_a_f[i] + int_b_f[i] + temp;
		temp = int(res / ARY);

		char buffer[1024];
		sprintf_s(buffer, "%d\0", res % ARY);
		string str_temp(buffer);

		for (int x = str_temp.size(); x < DIGIT; x++)
		{
			str_temp = "0" + str_temp;
		}

		f_str = str_temp + f_str;
	}

	for (int i = int_a_i.size() - 1; i >= 0; i--)
	{
		int res = int_a_i[i] + int_b_i[i] + temp;
		temp = int(res / ARY);

		char buffer[1024];
		sprintf_s(buffer, "%d\0", res % ARY);
		string str_temp(buffer);

		for (int x = str_temp.size(); x < DIGIT; x++)
		{
			str_temp = "0" + str_temp;
		}

		i_str = str_temp + i_str;
	}
	if (temp > 0)
	{
		char buffer[1024];
		sprintf_s(buffer, "%d\0", temp % ARY);
		string str_temp(buffer);
		i_str = str_temp + i_str;

		temp = 0;
	}

	DoDelFront(i_str);
	DoDelBack(f_str);

	if (i_str == "")
		i_str = "0";
	if (f_str == "")
		f_str = "0";
	string res_str = "";
	if (f_str == "0")
		res_str = i_str;
	else
		res_str = i_str + "." + f_str;
	if (is_fushu == "-")
		res_str = is_fushu + res_str;
	return res_str;
}
//减
string calculator::DoSub(const string &a, const string &b)
{
	string is_fushu = "";
	string f_str = "";
	string i_str = "";

	string aa = a;
	string bb = b;
	if (a[0] == '-')
		aa.erase(aa.begin());
	if (b[0] == '-')
		bb.erase(bb.begin());

	vector<int> int_a_i; //a整数部分
	vector<int> int_a_f; //a小数部分
	vector<int> int_b_i; //b整数部分
	vector<int> int_b_f; //b小数部分

	if (a[0] == '-')
	{
		if (b[0] == '-')
		{
			return DoSub(bb, aa);
		}
		else
		{
			return DoAdd(aa, bb);
		}
	}
	else 
	{
		if (b[0] == '-')
		{
			return DoAdd(aa, bb);
		}
	}

	DoCalBase(aa, bb, int_a_i, int_b_i, int_a_f, int_b_f);
	DoToAlign(int_a_i, int_b_i, int_a_f, int_b_f);

	if (is_fushu == "")
	{
		for (int i = 0; i < int_a_i.size(); i++)
		{
			if (int_a_i[i] < int_b_i[i])
			{
				is_fushu = "-";
				break;
			}
			else if (int_a_i[i] > int_b_i[i])
			{
				is_fushu = "+";
				break;
			}
		}
	}
	if (is_fushu == "")
	{
		for (int i = int_a_f.size() - 1; i >= 0; i--)
		{
			if (int_a_f[i] < int_b_f[i])
			{
				is_fushu = "-";
				break;
			}
			else if (int_a_f[i] > int_b_f[i])
			{
				is_fushu = "+";
				break;
			}
		}
	}

	int temp = 0;
	if (is_fushu == "+")
	{
		for (int i = int_a_f.size() - 1; i >= 0; i--)
		{
			int res = int_a_f[i] - temp - int_b_f[i];
			if (res < 0)
			{
				res = res + ARY;
				temp = 1;
			}
			else
			{
				temp = 0;
			}
			char buffer[1024];
			sprintf_s(buffer, "%d\0", res);
			string str_temp(buffer);

			for (int x = str_temp.size(); x < DIGIT; x++)
			{
				str_temp = "0" + str_temp;
			}

			f_str = str_temp + f_str;
		}

		for (int i = int_a_i.size() - 1; i >= 0; i--)
		{
			int res = int_a_i[i] - temp - int_b_i[i];
			if (res < 0)
			{
				res = res + ARY;
				temp = 1;
			}
			else
			{
				temp = 0;
			}
			char buffer[1024];
			sprintf_s(buffer, "%d\0", res);
			string str_temp(buffer);

			for (int x = str_temp.size(); x < DIGIT; x++)
			{
				str_temp = "0" + str_temp;
			}

			i_str = str_temp + i_str;
		}
	}
	else if(is_fushu == "-")
	{
		for (int i = int_a_f.size() - 1; i >= 0; i--)
		{
			int res = int_b_f[i] - temp - int_a_f[i];
			if (res < 0)
			{
				res = res + ARY;
				temp = 1;
			}
			else
			{
				temp = 0;
			}
			char buffer[1024];
			sprintf_s(buffer, "%d\0", res);
			string str_temp(buffer);

			for (int x = str_temp.size(); x < DIGIT; x++)
			{
				str_temp = "0" + str_temp;
			}

			f_str = str_temp + f_str;
		}

		for (int i = int_a_i.size() - 1; i >= 0; i--)
		{
			int res = int_b_i[i] - temp - int_a_i[i];
			if (res < 0)
			{
				res = res + ARY;
				temp = 1;
			}
			else
			{
				temp = 0;
			}
			char buffer[1024];
			sprintf_s(buffer, "%d\0", res);
			string str_temp(buffer);

			for (int x = str_temp.size(); x < DIGIT; x++)
			{
				str_temp = "0" + str_temp;
			}

			i_str = str_temp + i_str;
		}
	}
	else
	{
		i_str = "0";
		f_str = "0";
	}

	DoDelFront(i_str);
	DoDelBack(f_str);

	if (i_str == "")
		i_str = "0";
	if (f_str == "")
		f_str = "0";
	string res_str = "";
	if (f_str == "0")
		res_str = i_str;
	else
		res_str = i_str + "." + f_str;
	if (is_fushu == "-")
		res_str = is_fushu + res_str;
	return res_str;
}
//乘
string calculator::DoMul(const string &a, const string &b)
{
	string f_str = "";
	string i_str = "";
	string is_fushu = "";

	string aa = a;
	string bb = b;
	if (a[0] == '-')
		aa.erase(aa.begin());
	if (b[0] == '-')
		bb.erase(bb.begin());

	if (a[0] == '-' && b[0] != '-')
		is_fushu = "-";
	if (b[0] == '-' && a[0] != '-')
		is_fushu = "-";

	vector<int> int_a_i; //a整数部分
	vector<int> int_b_i; //b整数部分

	int n = 0;
	DoToDelPoint(n, aa, bb, int_a_i, int_b_i);

	for (int j = int_b_i.size() - 1; j >= 0; j--)
	{
		string res_temp = "";
		int temp = 0;
		for (int i = int_a_i.size() - 1; i >= 0; i--)
		{
			int res = int_a_i[i] * int_b_i[j] + temp;
			temp = int(res / ARY);

			char buffer[1024];
			sprintf_s(buffer, "%d\0", res % ARY);
			string str_temp(buffer);

			for (int x = str_temp.size(); x < DIGIT; x++)
			{
				str_temp = "0" + str_temp;
			}

			res_temp = str_temp + res_temp;
		}
		if (temp > 0)
		{
			char buffer[1024];
			sprintf_s(buffer, "%d\0", temp % ARY);
			string str_temp(buffer);
			res_temp = str_temp + res_temp;

			temp = 0;
		}

		DoDelFront(res_temp);
		if (res_temp != "")
		{
			for (int k = 0; k < int_b_i.size() - 1 - j; k++)
			{
				string stemp = "";
				for (int x = 0; x < DIGIT; x++)
					stemp = stemp + "0";
				res_temp = res_temp + stemp;
			}
			i_str = DoAdd(i_str, res_temp);
		}
	}
	int i_str_size = i_str.size();
	if (i_str_size <= n)
	{
		for (int i = i_str_size; i <= n; i++)
			i_str = "0" + i_str;
	}
	for (int i = 0; i < n; i++)
	{
		f_str = i_str[i_str.size() - 1] + f_str;
		i_str.erase(i_str.end()-1);
	}

	DoDelFront(i_str);
	DoDelBack(f_str);

	if (i_str == "")
		i_str = "0";
	if (f_str == "")
		f_str = "0";
	string res_str = "";
	if (f_str == "0")
		res_str = i_str;
	else
		res_str = i_str + "." + f_str;

	if (is_fushu == "-")
		res_str = is_fushu + res_str;
	return res_str;
}
//除
string calculator::DoDiv(const string &a, const string &b)
{
	string f_str = "";
	string i_str = "";
	string is_fushu = "";
	string res_str = "";
	string aa = a;
	string bb = b;
	if (a[0] == '-')
		aa.erase(aa.begin());
	if (b[0] == '-')
		bb.erase(bb.begin());

	if (a[0] == '-' && b[0] != '-')
		is_fushu = "-";
	if (b[0] == '-' && a[0] != '-')
		is_fushu = "-";

	string str_a_i; //a整数部分
	string str_b_i; //b整数部分

	DoToBeInt(aa, bb, str_a_i, str_b_i);

	{
		if(str_b_i.size() <= 9) //被除数如果在int范围内 则可以用除法去算.
		{
			int b_i = atoi(str_b_i.c_str());
			if(b_i == 0)
				return "0";
			string x = "1000000000";
			vector<int> int_a_i; //每9位分割 

			//每9位分割
			int number = str_a_i.size() / 9 + 1; //多少个元素
			int count = str_a_i.size() % 9;  //第一个元素有多少个字符
			string str_temp = "";
			int now_count = 0;
			for (; now_count < count; now_count++)
			{
				str_temp = str_temp + str_a_i[now_count];
			}

			if (str_temp != "")
			{
				int_a_i.push_back(atoi(str_temp.c_str()));
				str_temp = "";
			}

			for (int j = 1; j < number; j++)
			{
				bool is_push = false;
				for (int i = 0; i < 9; i++, now_count++)
				{
					if (str_a_i[now_count] != '0')
						is_push = true;
					if (is_push)
						str_temp = str_temp + str_a_i[now_count];
				}
				if (str_temp == "")
					str_temp = "0";
				int_a_i.push_back(atoi(str_temp.c_str()));
				str_temp = "";
			}
			//计算
			for(int i = 0;i < int_a_i.size();i++)
			{
				double res = double(int_a_i[i])/double(b_i);

				char buffer1[1024];
				sprintf_s(buffer1, "%lf\0", res);
				string str(buffer1);
				char buffer2[1024];
				sprintf_s(buffer2, "%d\0", int_a_i.size() - 1 - i);
				string cifang(buffer2);

				string thpower = DoTHPOWER(x, cifang);
				str = DoMul(str, thpower);
				res_str = DoAdd(res_str, str);
			}
		}
		else
		{
			string temp_a = str_a_i;
			int res = 0;
			int max_point = 100; // 最多小数点后100位
			int point = 0;
			while(1)
			{
				if(temp_a == "0")
					break;
				if(point >= max_point)
				{
					point--;
					break;
				}
				
				string temp = DoSub(temp_a, str_b_i);
				if(temp[0] == '-')
				{
					point++;
					char buffer[1024];
					sprintf_s(buffer, "%d\0", res);
					string str_temp(buffer);
					i_str = i_str + str_temp;
					res = 0;
					temp_a.push_back('0');
				}
				else
				{
					temp_a = temp;
					res++;
				}
			}
			if(res != 0)
			{
				char buffer[1024];
				sprintf_s(buffer, "%d\0", res);
				string str_temp(buffer);
				i_str = i_str + str_temp;
				res = 0;
			}

			int i_str_size = i_str.size();
			if (i_str_size < point)
			{
				for (int i = i_str_size; i <= point; i++)
					i_str = "0" + i_str;
			}
			for (int i = 0; i < point; i++)
			{
				f_str = i_str[i_str.size() - 1] + f_str;
				i_str.erase(i_str.end()-1);
			}
			DoDelFront(i_str);
			DoDelBack(f_str);

			if (i_str == "")
				i_str = "0";
			if (f_str == "")
				f_str = "0";

			if (f_str == "0")
				res_str = i_str;
			else
				res_str = i_str + "." + f_str;

			if (is_fushu == "-")
				res_str = is_fushu + res_str;
		}
	}

	return res_str;
}
//次方
string calculator::DoTHPOWER(const string &a, const string &b)
{
	string str = "";
	string aa = a;
	string bb = "";
	if(b[0] == '-')
		aa = DoDiv("1",aa);

	for(int i = 0; i < b.size();i++)
	{
		if(b[i] == '.')
			break;
		if(b[i] >= '0' && b[i] <= '9')
			bb.push_back(b[i]);
	}
	if(bb == "")
		return str;
	if(bb == "0")
		return "1";

	int b_i = atoi(bb.c_str());

	for (int i = 0; i < b_i; i++)
	{
		if (str == "")
			str = "1";
		str = DoMul(str, aa);
	}

	return str;
}
//阶乘
string calculator::DoFACTORIAL(const string &aa)
{
	string a = aa;
	string is_fushu = "";
	if(a[0] == '-')
	{
		a.erase(a.begin());
		is_fushu = "-";
	}

	string i_str = "1";

	int int_temp = 1;
	int int_end = atoi(a.c_str());

	if (int_end == 0)
	{
		i_str = "";
		return i_str;
	}

	for (int i = 1; i < int_end;)
	{
		i++;
		char buffer[1024];
		sprintf_s(buffer, "%d\0", i);
		string str_temp(buffer);

		i_str = DoMul(i_str, str_temp);
	}
	i_str = is_fushu + i_str;
	return i_str;
}
//负号
string calculator::DoNegativeNumber(const string &a) 
{
	string str = "-";
	if(a[0] == '-')
	{
		str = a;
		str.erase(str.begin());
	}
	else 
	{
		str = str + a;
	}
	return str;
}

int main()
{
	calculator cal;
	cout << "请输入公式:" << endl;
	while (!cal.PutIn() || !cal.Change())
	{
		cout << "输入有误,请重新输入" << endl;
	}
	__int64 t1 = 0;
	__int64 t2 = 0;
	t1 = clock();
	cal.GetResult();
	t2 = clock();
	cal.PutOut();
	cout << endl << "用了 " << t2 - t1 << "ms" << endl;

	system("pause");
	return 0;
}




 
  
 
  
 
   
  


猜你喜欢

转载自blog.csdn.net/sukeychen/article/details/51051704