码迷,mamicode.com
首页 > 其他好文 > 详细

逆波兰计算器

时间:2018-03-10 15:57:17      阅读:450      评论:0      收藏:0      [点我收藏+]

标签:ctr   target   执行   括号   blank   tle   浮点   转化   change   

对于我们数学中常见的中缀表达式如 1+2 我们能很好的理解和判断优先级,但对于编程而言就显得非常的繁琐,但可以转化为后缀表达式也就是逆波兰式如 1+2变成1 2 + ,这样一来编写程序来计算就变得容易起来,计算逆波兰式在计算机上主要是利用栈结构来存储,对于一个逆波兰式如 1 2 + 3 *,(本来的中缀表达式应该是(1+2)*3),计算过程如下:假设现在是用字符串存储的逆波兰式,从头到尾遍历一遍,是数字就入栈,是运算符就出栈两个数进行对应的运算后再入栈,到最后栈中只剩下一个元素也就是结果了。具体过程为:1入栈,2入栈,遇到 +,2出栈,1出栈,1+2 = 3入栈,3入栈,遇到 *,出栈 3,出栈 3,入栈3*3 = 9,结束。这里没用到减法和除法,这两种运算需要考虑运算顺序,是后出栈的数除或减先出栈的数。

 

逆波兰式的计算很简单,难的是在于将普通式转化为逆波兰式

直接记住转化规则:

如果是数字,直接打印这个数字

如果是左括号也就是‘(‘,直接入栈。

如果是‘)‘,一直出栈并打印直到遇到‘(‘,这里‘)‘不再入栈。

如果是‘+‘ 或 ‘-‘,一直出栈并打印直到遇到‘(‘或者到栈底的时候停止出栈,然后‘+‘或‘-‘入栈。

如果是‘*‘或‘/‘,一直出栈并打印直到遇到‘+‘或‘-‘或‘(‘或栈底停止出栈,然后‘*‘或‘/‘入栈。

当结束时若栈不为空,出栈并打印栈中全部元素

举个例:(1+2)*3/4转化为逆波兰式

首先‘(‘入栈,栈中为‘(‘,打印为空。

1直接打印,栈中为‘(‘,打印为1。

‘+‘因为栈底为‘(‘,不需要出栈任何元素直接入栈,栈中为‘(‘,‘+‘,打印为1。

2直接打印,栈中为‘(‘,‘+‘,打印为1  2。

‘)‘出栈并打印‘+‘,然后遇到‘(‘停止出栈,接着出栈掉‘(‘,栈中为空,打印为1  2  +。

‘*‘因为栈为空直接入栈,栈中为‘*‘,打印为1  2  +。

3直接打印,栈中为空,打印为1  2  +  3。

‘/‘出栈并打印‘/‘,然后遇到栈底,结束出栈,入栈‘/‘,栈中为‘/‘,打印为1  2  +  3  *。

4直接打印,栈中为栈中为‘/‘,打印为1  2  +  3  *  4。

结束时栈中还有‘/‘,出栈并打印,栈中为‘/‘,打印为1  2  +  3  *   4  /。

结果就为1  2  +  3  *   4  /

逆波兰表达式的计算

从头到尾遍历一遍逆波兰表达式,如果是数字就直接入栈,如果是运算符就出栈两个数进行运算后结果入栈。

当遍历完以后栈中所剩的一个数就是最终结果。

接着上例:

1, 2依次入栈。

+出栈1 2执行+然后结果3入栈。

3入栈。

* 出栈3 3进行*然后入栈结果9.

4入栈。

/出栈9 4进行/然后入栈9/4。

结果就是9/4=2.25。

最后贴上代码:

 

[cpp] view plain copy
 
  1. //因为是随手写来练习一下就不考虑小数和负数的情况了,那样会耽误很多时间  
  2. #include<iostream>  
  3. #include<cmath>  
  4. #include<string>  
  5. using namespace std;  
  6.   
  7. //虽然有现成的模板类stack但最后还是手写了一个  
  8. template<typename anytype>  
  9. class MyStack{  
  10.    struct element{  
  11.       anytype Data;  
  12.       element* last;  
  13.    };  
  14.    element* top;  
  15. public:  
  16.    MyStack():top(NULL){}  
  17.    ~MyStack(){  
  18.       element* pointer;  
  19.       while(top!=NULL){  
  20.          pointer=top;  
  21.          delete pointer;  
  22.       }  
  23.    }  
  24.    void push(anytype x){  
  25.       element* pointer=new element;  
  26.       pointer->Data=x;  
  27.       pointer->last=top;  
  28.       top=pointer;  
  29.    }  
  30.   
  31.    anytype pop(){  
  32.       if(top!=NULL){  
  33.          anytype PopData=top->Data;  
  34.          element* pointer=top;  
  35.          top=top->last;  
  36.          delete pointer;  
  37.          return PopData;  
  38.       }  
  39.       else{  
  40.          return 0;  
  41.       }  
  42.    }  
  43.    anytype GetTop(){  
  44.       if(top!=NULL){  
  45.          return top->Data;  
  46.       }  
  47.       else{  
  48.          return 0;  
  49.       }  
  50.    }  
  51. };  
  52.   
  53. //定于一个函数用于将普通表达式转化为逆波兰表达式  
  54. string change(string x){  
  55.    int len=x.size();  
  56.    string ans;  
  57.    MyStack<char> operators;  
  58.    for(int i=0;i<len;i++){  
  59.       if(x[i]>=‘0‘&&x[i]<=‘9‘){  
  60.          int j;  
  61.          for(j=i;x[j]>=‘0‘&&x[j]<=‘9‘;j++){  
  62.             ans+=x[j];  
  63.          }  
  64.          ans+=‘ ‘;  
  65.          i=j-1;  
  66.       }  
  67.       else if(x[i]==‘(‘){  
  68.          operators.push(x[i]);  
  69.       }  
  70.       else if(x[i]==‘*‘||x[i]==‘/‘){  
  71.          while(operators.GetTop()==‘*‘||operators.GetTop()==‘/‘){  
  72.             ans+=operators.pop();  
  73.          }  
  74.          operators.push(x[i]);  
  75.       }  
  76.       else if(x[i]==‘)‘){  
  77.          while(operators.GetTop()!=‘(‘){  
  78.             ans+=operators.pop();  
  79.          }  
  80.          operators.pop();  
  81.       }  
  82.       else if(x[i]==‘+‘||x[i]==‘-‘){  
  83.          while(operators.GetTop()!=‘(‘&&operators.GetTop()!=0){  
  84.             ans+=operators.pop();  
  85.             ans+=‘ ‘;  
  86.          }  
  87.          operators.push(x[i]);  
  88.       }  
  89.    }  
  90.    while(operators.GetTop()!=0){  
  91.       ans+=operators.pop();  
  92.       ans+=‘ ‘;  
  93.    }  
  94.    return ans;  
  95. }  
  96.   
  97. //随手写的一个将字符串存储的数字转化为整型数的函数 这里就不考虑小数负数的情况了  
  98. long long ToNum(string x){  
  99.    int len=x.size();  
  100.    long long ans=0;  
  101.    for(int i=0;i<len;i++){  
  102.       ans+=(x[i]-‘0‘)*pow(10.0,len-i-1)+0.5;//测试了几下pow函数可能会出现浮点数误差就四舍五入来保证精度  
  103.    }  
  104.    return ans;  
  105. }  
  106.   
  107. double calculate(string x){  
  108.    x=change(x);  
  109.    string temp;  
  110.    MyStack<double> ans; //为了除法运算方便使用double  
  111.    int len=x.size();  
  112.    for(int i=0;i<len;i++){  
  113.       if(x[i]==‘ ‘)continue;  
  114.       if(x[i]>=‘0‘&&x[i]<=‘9‘){  
  115.          temp="";  
  116.          int j;  
  117.          for(j=i;x[j]>=‘0‘&&x[j]<=‘9‘;j++){  
  118.             temp+=x[j];  
  119.          }  
  120.          i=j-1;  
  121.          ans.push(ToNum(temp));  
  122.       }  
  123.       else{  
  124.          double a=ans.pop(),b=ans.pop();//对于减和乘需要考虑运算顺序所以额外定义两个变量  
  125.          switch(x[i]){  
  126.             case ‘+‘:{ans.push(a+b);break;}  
  127.             case ‘-‘:{ans.push(b-a);break;}  
  128.             case ‘*‘:{ans.push(a*b);break;}  
  129.             case ‘/‘:{ans.push(b/a);break;}  
  130.          }  
  131.       }  
  132.    }  
  133.    return ans.pop();  
  134. }  
  135.   
  136. int main(){  
  137.    string x;  
  138.    cout<<"Please input data."<<endl<<"And don‘t use chinese brackets and don‘t input negative and decimals and space."<<endl;  
  139.    while(cin>>x){  
  140.       cout<<endl<<"answer = "<<calculate(x)<<endl<<endl<<"continue to input or input ctrl+z to break."<<endl;  
  141.    }  
  142. }  

逆波兰计算器

标签:ctr   target   执行   括号   blank   tle   浮点   转化   change   

原文地址:https://www.cnblogs.com/TAMING/p/8538907.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!