<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-26  評論-111  文章-19  trackbacks-0

           對四則運算表達式字符串進行解析后計算出結果,可以使用逆波蘭表達式進行處理。

           首先說明一下什是逆波蘭表達式:

            逆波蘭表達式又叫做后綴表達式。在通常的表達式中,二元運算符總是置于與之相關的兩個運算對象之間,所以,這種表示法也稱為中綴表示。波蘭邏輯學家J.Lukasiewicz于1929年提出了另一種表示表達式的方法。按此方法,每一運算符都置于其運算對象之后,故稱為后綴表示。


      將一個普通的中序表達式轉換為逆波蘭表達式的一般算法是:
      (
    1)首先構造一個運算符棧,此運算符在棧內遵循越往棧頂優先級越高的原則。
      (
    2)讀入一個用中綴表示的簡單算術表達式,為方便起見,設該簡單算術表達式的右端多加上了優先級最低的特殊符號“#”。
      (
    3)從左至右掃描該算術表達式,從第一個字符開始判斷,如果該字符是數字,則分析到該數字串的結束并將該數字串直接輸出。
      (
    4)如果不是數字,該字符則是運算符,此時需比較優先關系。
      做法如下:將該字符與運算符棧頂的運算符的優先關系相比較。如果,該字符優先關系高于此運算符棧頂的運算符,則將該運算符入棧。倘若不是的話,則將棧頂的運算符從棧中彈出,直到棧頂運算符的優先級低于當前運算符,將該字符入棧。
      (
    5)重復上述操作(3)-(4)直至掃描完整個簡單算術表達式,確定所有字符都得到正確處理,我們便可以將中綴式表示的簡單算術表達式轉化為逆波蘭表示的簡單算術表達式。
                                                                          
             以上內容來源百度


            下面進入正題,按照以上的算法說明自己實現四則運算如下:

      1 package com.snoics.jdk.arithmetic;
      2 
      3 import java.math.BigDecimal;
      4 import java.math.RoundingMode;
      5 import java.util.ArrayList;
      6 import java.util.LinkedList;
      7 import java.util.List;
      8 
      9 /**
     10  * 
     11  *  通過四則運算表達式字符串,構造逆波蘭表達式,計算結果
     12  *  
     13    *  (1)從左至右掃描該算術表達式,從第一個字符開始判斷,
     14  *            如果該字符是數字,則分析到該數字串的結束并將該數字串直接輸出。
     15  * 
     16  * (2)如果不是數字,該字符則是運算符,此時需比較優先關系。
     17           做法如下:將該字符與運算符棧頂的運算符的優先關系相比較。
     18                                            如果,該字符優先關系高于此運算符棧頂的運算符,則將該運算符入棧。
     19                                            倘若不是的話,則將棧頂的運算符從棧中彈出,直到棧頂運算符的優先級
     20                                            低于當前運算符,將該字符入棧。
     21                                            
     22   (3)重復上述操作(1)-(2)直至掃描完整個簡單算術表達式,確定所有字符都得到正確處理,
     23                     我們便可以將中綴式表示的簡單算術表達式轉化為逆波蘭表示的簡單算術表達式。
     24  * 
     25  * @author:shiwei
     26  * 
     27  * 
     28  */
     29 public class Arithmetic {
     30     
     31     /**
     32      * +
     33      */
     34     private final static String OP1 = "+";
     35     
     36     /**
     37      * -
     38      */
     39     private final static String OP2 = "-";
     40     
     41     /**
     42      * *
     43      */
     44     private final static String OP3 = "*";
     45     
     46     /**
     47      * /
     48      */
     49     private final static String OP4 = "/";
     50     
     51     /**
     52      * (
     53      */
     54     private final static String OPSTART = "(";
     55     
     56     /**
     57      * )
     58      */
     59     private final static String OPEND = ")";
     60 
     61     //四則運算式
     62     private String exp;
     63     
     64     //精確到小數點后幾位
     65     private int precision=2;
     66     
     67     //取舍模式
     68     private RoundingMode roundingMode=RoundingMode.HALF_UP;
     69     
     70     //四則運算解析
     71     private List<String> expList = new ArrayList<String>();
     72 
     73     //存放逆波蘭表達式
     74     private List<String> rpnList = new ArrayList<String>();
     75 
     76     /**
     77      * 四則運算
     78      * @param exp            四則運算表達式
     79      * @param precision        精確到小數點后幾位
     80      * @param roundingMode        取舍模式
     81      */
     82     public Arithmetic(String exp,int precision,RoundingMode roundingMode) {
     83         this.exp = exp;
     84         this.precision=precision;
     85         this.roundingMode=roundingMode;
     86         
     87         parse();
     88         createRPN();
     89     }
     90 
     91     /**
     92      * 分析四則運算表達式,將數字與運算符進行分解
     93      */
     94     private void parse() {
     95         int length = exp.length();
     96 
     97         String tempStr = "";
     98         for (int i = 0; i < length; i++) {
     99             String tempChar = exp.substring(i, i + 1);
    100             if (isNumber(tempChar)) {
    101                 tempStr += tempChar;
    102             } else {
    103                 if (!tempStr.equals("")) {
    104                     expList.add(tempStr);
    105                 }
    106                 expList.add(tempChar);
    107                 tempStr = "";
    108             }
    109         }
    110         if (!tempStr.equals("")) {
    111             expList.add(tempStr);
    112         }
    113         
    114     }
    115 
    116     /**
    117      * 判斷當前字符或字符串是否是數字
    118      * @param str
    119      * @return
    120      */
    121     private boolean isNumber(String str) {
    122         return str.startsWith("0"
    123                 || str.startsWith("1")
    124                 || str.startsWith("2"
    125                 || str.startsWith("3")
    126                 || str.startsWith("4"
    127                 || str.startsWith("5")
    128                 || str.startsWith("6"
    129                 || str.startsWith("7")
    130                 || str.startsWith("8"
    131                 || str.startsWith("9"
    132                 || str.startsWith(".");
    133 
    134     }
    135 
    136     /**
    137      * 判斷當前字符是否是 (
    138      * @param str
    139      * @return
    140      */
    141     private boolean isParenthesesStart(String str) {
    142         return str.equals(OPSTART);
    143     }
    144 
    145     /**
    146      * 判斷當前字符是否是  )
    147      * @param str
    148      * @return
    149      */
    150     private boolean isParenthesesEnd(String str) {
    151         return str.equals(OPEND);
    152     }
    153 
    154     /**
    155      * 判斷當前字符是否是高優先級運算符  * /
    156      * @param str
    157      * @return
    158      */
    159     private boolean isHeighOperator(String str) {
    160         if (str.equals(OP3) 
    161                 || str.equals(OP4)) {
    162             return true;
    163         } else {
    164             return false;
    165         }
    166     }
    167 
    168     /**
    169      * 對比兩個字符串的優先級
    170      * @param str1
    171      * @param str2
    172      * @return
    173      */
    174     private boolean compare(String str1, String str2) {
    175         if (str1.equals(OPSTART)) {
    176             return false;
    177         }
    178         if (isHeighOperator(str2)) {
    179             return false;
    180         } else {
    181             if (isHeighOperator(str1)) {
    182                 return true;
    183             } else {
    184                 return false;
    185             }
    186         }
    187     }
    188 
    189     /**
    190      * 將分解后的四則運算列表構建成逆波蘭表達式列表
    191      */
    192     private void createRPN() {
    193         Stack stack = new Stack();
    194         
    195         int length = expList.size();
    196         for (int i = 0; i < length; i++) {
    197             String c = expList.get(i);
    198             
    199             //如果是數字,直接放到逆波蘭鏈表的最后
    200             if (isNumber(c)) {
    201                 rpnList.add(c);
    202             } else {
    203                 //如果不是數字
    204                 
    205                 //如果是左括號,則直接將左括號壓入棧
    206                 if (isParenthesesStart(c)) {
    207                     stack.push(c);
    208                 } else if (isParenthesesEnd(c)) {
    209                     //如果是右括號
    210                     
    211                     //進行出棧操作,直到棧為空或者遇到第一個左括號
    212                     while (!stack.isEmpty()) {
    213                         //將棧頂字符串做出棧操作
    214                         String tempC = stack.pop();
    215                         if (!tempC.equals(OPSTART)) {
    216                             //如果不是左括號,則將字符串直接放到逆波蘭鏈表的最后
    217                             rpnList.add(tempC);
    218                         }else{
    219                             //如果是左括號,退出循環操作
    220                             break;
    221                         }
    222                     }
    223                 } else {
    224                     //如果棧內為空
    225                     if (stack.isEmpty()) {
    226                         //將當前字符串直接壓棧
    227                         stack.push(c);
    228                     } else {
    229                         //如果棧不為空
    230                         
    231                         //比較棧頂字符串與當前字符串的優先級,
    232                         if (compare(stack.top(), c)) {
    233                             //如果棧頂元素的優先級大于當前字符串,則進行出棧操作
    234                             //將棧頂元素直接放到逆波蘭鏈表的最后
    235                             //直到棧內為空,或者當前元素的優先級不小于棧頂元素優先級
    236                             while (!stack.isEmpty() && compare(stack.top(), c)) {
    237                                 rpnList.add(stack.pop());
    238                             }
    239                         }
    240                         //將當前字符串直接壓棧
    241                         stack.push(c);
    242                     }
    243                 }
    244 
    245             }
    246         }
    247 
    248         //如果棧不為空,則將棧中所有元素出棧放到逆波蘭鏈表的最后
    249         while (!stack.isEmpty()) {
    250             rpnList.add(stack.pop());
    251         }
    252     }
    253     
    254     /**
    255      * 通過逆波蘭表達式計算結果
    256      * @return
    257      */
    258     public String calculate(){
    259         Stack numberStack = new Stack();
    260         
    261         int length=rpnList.size();
    262         for(int i=0;i<length;i++){
    263             String temp=rpnList.get(i);
    264             if(isNumber(temp)){
    265                 numberStack.push(temp);
    266             }else{
    267                 BigDecimal tempNumber1 = getBigDecimal(numberStack.pop(),
    268                         precision,
    269                         roundingMode);
    270                 
    271                 BigDecimal tempNumber2 = getBigDecimal(numberStack.pop(),
    272                         precision,
    273                         roundingMode);
    274                 
    275                 BigDecimal tempNumber = getBigDecimal("",
    276                         precision,
    277                         roundingMode);  
    278                 
    279                 if(temp.equals(OP1)){
    280                     tempNumber=tempNumber2.add(tempNumber1);
    281                 }else if(temp.equals(OP2)){
    282                     tempNumber=tempNumber2.subtract(tempNumber1);
    283                 }else if(temp.equals(OP3)){
    284                     tempNumber=tempNumber2.multiply(tempNumber1);
    285                 }else if(temp.equals(OP4)){
    286                     tempNumber=tempNumber2.divide(tempNumber1,
    287                             precision,
    288                             roundingMode);
    289                 }
    290                 
    291                 numberStack.push(tempNumber.toString());
    292                 
    293             }
    294         }
    295         
    296         return numberStack.pop();
    297     }
    298     
    299     /**
    300      * 獲取逆波蘭表達式字符串
    301      * @return
    302      */
    303     public String getRPN(){
    304 
    305         String rpn="";
    306 
    307         int rpnLength=rpnList.size();
    308         for(int i=0;i<rpnLength;i++){
    309             rpn+=rpnList.get(i)+" ";
    310         }
    311         
    312         return rpn;
    313     }
    314     
    315     /**
    316      * 按精確度計算結果
    317      * @param numString
    318      * @param precision
    319      * @param roundingMode
    320      * @return
    321      */
    322     public static BigDecimal getBigDecimal(String numString,
    323             int precision,
    324             RoundingMode roundingMode){
    325         String precisionFlag="0";
    326         if(numString==null || numString.equals("")){
    327             precisionFlag="0.00";
    328         }else{
    329             precisionFlag=numString;
    330         }
    331         BigDecimal bigDecimal = new BigDecimal(precisionFlag);
    332         bigDecimal.setScale(precision,roundingMode);
    333         return bigDecimal;
    334     }
    335 
    336     /**
    337      * 棧
    338      *
    339      *
    340      * @author shiwei
    341      *
    342      */
    343     private class Stack {
    344         
    345         LinkedList<String> stackList = new LinkedList<String>();
    346 
    347         public Stack() {
    348             
    349         }
    350 
    351         /**
    352          * 入棧
    353          * @param expression
    354          */
    355         public void push(String expression) {
    356             stackList.addLast(expression);
    357         }
    358 
    359         /**
    360          * 出棧
    361          * @return
    362          */
    363         public String pop() {
    364             return stackList.removeLast();
    365         }
    366 
    367         /**
    368          * 棧頂元素
    369          * @return
    370          */
    371         public String top() {
    372             return stackList.getLast();
    373         }
    374 
    375         /**
    376          * 棧是否為空
    377          * @return
    378          */
    379         public boolean isEmpty() {
    380             return stackList.isEmpty();
    381         }
    382     }
    383 
    384     public static void main(String[] args) {
    385         
    386         String str = "1+(2+3)*(100-5*(9+8))/2.3+6-19";
    387 
    388         
    389         
    390 
    391         System.out.println("====================================");
    392         
    393         //將四則運算字符串分解為逆波蘭表達式后計算結果
    394         Arithmetic arithmetic=new Arithmetic(str,10,RoundingMode.HALF_UP);
    395         String rpn=arithmetic.getRPN();
    396         System.out.println("逆波蘭表達式 : "+rpn);
    397         System.out.println("計算結果 : "+arithmetic.calculate());
    398     }
    399 
    400 }
    401 

          最后的運行計算結果如下:

    ====================================
    逆波蘭表達式 : 1 2 3 + 100 5 9 8 + * - 2.3 / * 6 19 - + +
    計算結果 : 20.6086956520

    posted on 2010-07-29 17:44 snoics 閱讀(3399) 評論(2)  編輯  收藏

    評論:
    # re: 使用逆波蘭表達式進行四則運算 2010-07-30 10:22 | dasdas
    # re: 使用逆波蘭表達式進行四則運算 2010-07-30 10:59 | 凡客
    學習了  回復  更多評論
      

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲高清偷拍一区二区三区 | 国产精品黄页在线播放免费| 国产亚洲AV夜间福利香蕉149| 国产成人亚洲综合一区| a级毛片毛片免费观看久潮喷| 日韩电影免费在线观看视频| 亚洲情A成黄在线观看动漫软件| 国产jizzjizz视频全部免费| 亚洲熟伦熟女专区hd高清| 中文字幕无码视频手机免费看 | 中文字幕不卡亚洲 | 亚洲宅男天堂在线观看无病毒| 菠萝菠萝蜜在线免费视频| 久久99九九国产免费看小说| 久久精品国产亚洲AV无码娇色| caoporn成人免费公开| 四虎影视在线永久免费看黄| 男人j进入女人j内部免费网站| 亚洲熟女少妇一区二区| 在线观看免费人成视频色9| 三级网站在线免费观看| 亚洲日韩精品A∨片无码加勒比| 韩国日本好看电影免费看| 亚洲精品无码av片| 在线观看免费国产视频| 热re99久久6国产精品免费| 亚洲色偷偷av男人的天堂 | 久久99国产亚洲高清观看首页| 一级毛片免费在线观看网站| 国产亚洲精品拍拍拍拍拍| 国产免费久久久久久无码| 国产亚洲人成网站在线观看不卡| 99久久久国产精品免费蜜臀 | 毛片免费观看的视频在线| 亚洲精品无码av中文字幕| 亚洲AV无码久久精品成人 | 国产一级淫片a免费播放口| 亚洲网红精品大秀在线观看| 美女在线视频观看影院免费天天看| 欧美激情综合亚洲一二区| 伊伊人成亚洲综合人网7777|