您的位置:首页 > 其它

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

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

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

百度查到的定义是

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

一个表达式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+[b](3/5678)
* 10^1+[b](4/5678) * 10^0 这样,就可以较快的计算了。
[/b][/b]

[b][b]至于阶乘次方这些
基本的加减乘除出来以后,就迎刃而解了!
[/b][/b]

总结,需要注意以下几点:
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;
}








内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: