標籤:style blog http color io os 使用 ar strong
四則運算,最常用的當然是逆波蘭方法,現將運算式由中綴運算式轉化為尾碼運算式,然後再使用棧計算即可。這兩步下來,估計沒有三四百行代碼是實現不了的。
中綴運算式轉首碼尾碼運算式
將中綴運算式轉換為尾碼運算式的演算法思想:
數字時,加入尾碼運算式;
運算子:
a. 若為 ‘(‘,入棧;
b. 若為 ‘)‘,則依次把棧中的的運算子加入尾碼運算式中,直到出現‘(‘,從棧中刪除‘(‘ ;
c. 若為 除括弧外的其他運算子, 當其優先順序高於除‘(‘以外的棧頂運算子時,直接入棧。否則從棧頂開始,依次彈出比當前處理的運算子優先順序高和優先順序相等的運算子,直到一個比它優先順序低的或者遇到了一個左括弧為止。
高優先順序可以壓迫低優先順序!
人工實現轉換
這裡我給出一個中綴運算式:a+b*c-(d+e)
第一步:按照運算子的優先順序對所有的運算單位加括弧:式子變成了:((a+(b*c))-(d+e))
第二步:轉換首碼與尾碼運算式
首碼:把運算子號移動到對應的括弧前面 ,則變成了:-( +(a *(bc)) +(de)) ,把括弧去掉:-+a*bc+de 首碼式子出現。
尾碼:把運算子號移動到對應的括弧後面 ,則變成了:((a(bc)* )+ (de)+ )- ,把括弧去掉:abc*+de+- 尾碼式子出現。
比如:計算(2 + 1) * (13 + 5)
轉換後得:((2+1)*(13+5)) -> ((2 1) + (13 5) +) * -> 2 1 + 13 5 + *
這裡把尾碼運算式儲存到vector<string>中,實現棧的計算,如下:
int cal(int num1, int num2, string tag){ if ("+" == tag) { return num1 + num2; } else if ("-" == tag) { return num1 - num2; } else if ("*" == tag) { return num1*num2; } else { return num1 / num2; }}int evalRPN(vector<string> &tokens) { int result = 0; stack<int> nums; for (int i = 0; i<tokens.size(); i++) { string tag = tokens[i]; if (tag != "+"&&tag != "-"&&tag != "*"&&tag != "/") { //這是一個數字 nums.push(atoi(tag.c_str())); } else { //不是一個數字 int num2 = nums.top(); nums.pop(); int num1 = nums.top(); nums.pop(); result = cal(num1, num2, tag); nums.push(result); } } return result=nums.top();}
實際中遇到的筆試題是這樣的,有字串表示的一個四則運算運算式,要求計算出該運算式的正確數值,比如:5+17*8-4/2。
題目中沒有括弧,而且留白答題空超過半張紙,這裡只需要考慮四則運算的先後順序,是上述問題的特殊情況,程式實現運算規則即可。
思路:1+5*6+6/2-5...
要構建1+5*6+....的式子,計算到第二個加號時要保留三個數:第一項1,第二項5,以及當前項6,還有兩個符號+*,然後比較符號的優先順序合并兩項,更新符號。最後再考慮1+5、1、以及沒有數位情況。
/* *侯凱,2014-9-16 *功能:四則運算 */#include<iostream>#include <string>using namespace std;int cal(int nNum1, char op, int nNum2) { if(‘+‘ == op) { return nNum1 + nNum2; } if(‘-‘ == op) { return nNum1 - nNum2; } if(‘*‘ == op) { return nNum1 * nNum2; } if(‘/‘ == op) { return nNum1 / nNum2; } } int calculate(string str){ char op;//記錄上一個符號 char p; int num=0,factor1,factor2; int stage = 0; if(str.empty()) return 0; for(int i=0;i<str.size();i++) { if(str[i]>=‘0‘&&str[i]<=‘9‘) { num = num*10+(str[i]-‘0‘); } else { if(stage == 0) { factor1 = num; op = str[i]; stage = 1; } else if(stage == 1) { factor2 = num; p=str[i]; stage = 2; } else if(stage == 2) { //每次進入這裡,都儲存有a(op)b(p)的狀態如1+5*,這裡要做的就是更新a ,b ,op,p的工作了 if((p==‘/‘||p==‘*‘)&&(op==‘+‘||op==‘-‘)) { factor2 = cal(factor2,p,num); p=str[i]; } else { factor1 = cal(factor1,op,factor2); factor2 = num; op = p; p = str[i]; } } num = 0; } } float result; if(stage == 0) { return num; } if(stage == 1) { result = cal(factor1,op,num); return result; } if((p==‘/‘||p==‘*‘)&&(op==‘+‘||op==‘-‘)) { factor2 = cal(factor2,p,num); result = cal(factor1,op,factor2); } else { factor1 = cal(factor1,op,factor2); result = cal(factor1,p,num); } return result;}int main(){ string str = "1+16*7+5*2+3";//126 int res = calculate(str); cout<<res<<endl; system("Pause");}
這樣程式簡化了不少,百行代碼應該能搞定,雖然卷面上裝下依然不太現實
字串的四則運算