昨天突然想写个计算器,支持无限位数结果的。于是乎就写了个...现在把写的过程记录下来,供大家互相学习!
首先,要做计算,我首先想到的就是逆波兰。
百度查到的定义是
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
一个
表达式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; }