数据结构之栈的应用 计算器算法
记得去年十一月份还没进部门那段时间做的最后一个项目就是用MFC仿照Windows下的计算器写一个自己的简易计算器,当时老师含糊的说了句可以用到栈来实现计算机的功能,可是当时对于栈的概念真的非常模糊,甚至从来没有真正意义上的了解栈。所以就用自己的笨办法实现了标准型的计算器,由于进部门之后,介于Android零基础的学习让我倍感压力,所以就一直没有时间和精力去实现科学计算器
但是现在想想,就算当时我有时间去实现科学计算器,以我当时的算法,应该怎么也无法达到那个效果。但是虽然现在知道了栈的巧妙之处,但是MFC得知识真的已经忘得差不多了,所以还是按部就班的学完数据结构吧。
昨天写了一个迷宫的小程序,基本上用的是C++的知识,但是却没有一点C++的特点,所以今天在写简易计算功能的时候将栈的操作封装成一个类了。方便以后直接拿来用。
#pragma once #ifndef STACK_H #define STACK_H #include <string> using namespace std; typedef struct Node { string oper; struct Node *pTrNext; }NODE,*pNODE; // typedef struct Optd { // int num; // struct Optd *pTdNext; // }OPTD,*pOPTD; class CStack { private: pNODE pTop; pNODE pBottom; public: CStack (); bool IsNull(); void push(string opr); bool pop(string *pOpr); string getTop(); void clear(); ~CStack(); }; #endif
#include <iostream> #include "CStack.h" using namespace std; CStack::CStack() { pBottom = pTop = new NODE; pBottom->pTrNext = NULL; } bool CStack::IsNull(){ if(pTop == pBottom) { cout<<"Stack is null"; return true; } else return false; } void CStack::push(string opr) { pNODE p = new NODE; p->oper = opr; p->pTrNext = pTop; pTop = p; } bool CStack::pop(string *pOpr) { pNODE p = pTop; if(!IsNull()) pTop = p->pTrNext; else return false; *pOpr = p->oper; delete(p); return true; } string CStack::getTop() { if (IsNull()) return ""; else return pTop->oper; } void CStack::clear() { string temp; while(!IsNull()) pop(&temp); } CStack::~CStack() { clear(); }
今天在写个程序的时遇到最大的问题就是如何进行算法优先级的比较。早上六点多开始思考这个问题,一直到坐到办公室都没有想出更好的办法去解决这个问题~~~ 数学真心不给力,学习的路还很长远!!
看了一下android是如何实现的
String evaluate(String input) throws SyntaxException { if (input.trim().equals("")) { return ""; } // drop final infix operators (they can only result in error) int size = input.length(); while (size > 0 && isOperator(input.charAt(size - 1))) { input = input.substring(0, size - 1); --size; } // Find and replace any translated mathematical functions. input = replaceTranslations(input); double value = mSymbols.eval(input); String result = ""; for (int precision = mLineLength; precision > 6; precision--) { result = tryFormattingWithPrecision(value, precision); if (result.length() <= mLineLength) { break; } } return result.replace('-', MINUS).replace(INFINITY, INFINITY_UNICODE); }
其实真正起到计算的也就一行代码
double value = mSymbols.eval(input);
我们来看看mSymbols所在的类Symbols,该类所在的包为org.javia.arity.Symbols;
而该包所在的地方为计算器源码的arity-2.1.2.jar。该包在源码发布的时候就已经编译成jar了。所以看来谷歌并没有真正的开源啊。。。也或许是我的认知度太低,无法找到计算器的核心算法。。
看来还是得自己写一个算法优先级比较的简易函数吧。。
#include <iostream> #include "CStack.h" #include <string> #include <sstream> using namespace std; //string Aoperator[3][2] = {{"+","-"},{"*","/"},{"[","]"},{"(",")"}}; int getpriority(string opr); int IshighPriority(string Sopr,string Iopr);//1代表相等 2代表大于,0代表小于 double StringToDouble(string Input); string DoubleToString(double Input); double evaluate(string num1,string opr,string num2); bool isNumber(string s); string getx(string *s); int main() { string x; string formula; string result; CStack *OPRT = new CStack(); CStack *OPRD = new CStack(); OPRT->push("$"); cout<<"Please input your formula:"; cin>>formula; x=getx(&formula); while(IshighPriority(OPRT->getTop(),x) != -2) { if(isNumber(x)) { OPRD->push(x); x=getx(&formula); } else { switch(IshighPriority(OPRT->getTop(),x)) { case 0:{ OPRT->push(x); x=getx(&formula); break; } case 1:{ string temp; OPRT->pop(&temp); x=getx(&formula); break; } case 2:{ string num1; string num2; string opr; OPRT->pop(&opr); OPRD->pop(&num1); OPRD->pop(&num2); OPRD->push(DoubleToString(evaluate(num2,opr,num1))); break; } default: break; } } } // if(x=="$") { // string num1; // string num2; // string opr; // OPRT->pop(&opr); // OPRD->pop(&num1); // OPRD->pop(&num2); // OPRD->push(DoubleToString(evaluate(num1,opr,num2))); // } OPRD->pop(&result); cout<<result; return 0; } int getpriority(string opr) { // int i=0,j=0; // for(i=0;i<4;i++) { // for(j=0;j<2;j++) { // if(opr == Aoperator[i][j]); // break; // } // } // return i; if(opr == "+" || opr == "-") return 0; else if(opr == "*" || opr == "/") return 1; else if(opr == "[" || opr == "]") return 2; else if(opr == "(" || opr == ")") return 3; else if(opr == "$") return -2; else return -1; } string getx(string *s){ string x = s->substr(0,1); *s = s->substr(1,s->length()); return x; } bool isNumber(string s) { if(getpriority(s) == -1) return true; else return false; } int IshighPriority(string Sopr,string Iopr) { if(getpriority(Sopr) == getpriority(Iopr)) { if(Iopr == "$") return -2; else if (Iopr== ")"||Iopr == "]") { return 1; } else return 2; } else if(getpriority(Sopr) < getpriority(Iopr)) { if(Iopr == ")"||Iopr == "]") return 2; return 0; } else if(getpriority(Sopr) > getpriority(Iopr)) { if((Sopr != "(")&&Sopr !="[") return 2; else return 0; } else return -1; //错误 } double StringToDouble(string Input) { double Result; stringstream Oss; Oss<<Input; Oss>>Result; return Result; } string DoubleToString(double Input) { stringstream Oss; Oss<<Input; return Oss.str(); } double evaluate(string num1,string opr,string num2) { if(opr == "+") return StringToDouble(num1)+StringToDouble(num2); else if(opr == "-") return StringToDouble(num1)-StringToDouble(num2); else if(opr == "*") return StringToDouble(num1)*StringToDouble(num2); else return StringToDouble(num1)/StringToDouble(num2); }
由于只是熟悉一下该算法,所以我在实现该算法的前提就是:所输入的计算公式完全正确。