亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

java實(shí)現(xiàn)任意四則運(yùn)算表達(dá)式求值算法

 更新時(shí)間:2015年04月20日 15:03:30   作者:司青  
這篇文章主要介紹了java實(shí)現(xiàn)任意四則運(yùn)算表達(dá)式求值算法,實(shí)例分析了基于java實(shí)現(xiàn)表達(dá)式四則運(yùn)算求值的原理與技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下

本文實(shí)例講述了java實(shí)現(xiàn)任意四則運(yùn)算表達(dá)式求值算法。分享給大家供大家參考。具體分析如下:

該程序用于計(jì)算任意四則運(yùn)算表達(dá)式。如 4 * ( 10 + 2 ) + 1 的結(jié)果應(yīng)該為 49。
算法說(shuō)明:

1. 首先定義運(yùn)算符優(yōu)先級(jí)。我們用一個(gè)

Map<String, Map<String, String>>

來(lái)保存優(yōu)先級(jí)表。這樣我們就可以通過(guò)下面的方式來(lái)計(jì)算兩個(gè)運(yùn)算符的優(yōu)先級(jí)了:

/**
 * 查表得到op1和op2的優(yōu)先級(jí)
 * @param op1 運(yùn)算符1
 * @param op2 運(yùn)算符2
 * @return ">", "<" 或 "="
 */
public String priority(String op1, String op2) {
 return priorityMap.get(op1).get(op2);
}

2. 掃描表達(dá)式字符串,每次讀入一個(gè) token 進(jìn)行處理。

使用兩個(gè)輔助棧:optStack用于保存運(yùn)算符,numStack用于保存操作數(shù). 我們用 '#' 作為表達(dá)式的起始和結(jié)果標(biāo)志符。

讀入一個(gè)token,如果它是數(shù)字,則壓入numStack棧中;

如果它是運(yùn)算符,則取出optStack棧的棧頂元素A,將 A 與 token 進(jìn)行優(yōu)先級(jí)比較。

如果 A < token,則將 token 壓入optStack棧。

如果 A = token,則說(shuō)明 token和A是一對(duì)括號(hào),此時(shí)將optStack棧的棧頂元素彈出。

如果 A > token,則從numStack中彈出2個(gè)操作數(shù),從optStack中彈出1個(gè)運(yùn)算符,并計(jì)算結(jié)果。

當(dāng)optStrack棧為空時(shí)(即棧頂元素為 '#'),numStack棧的棧頂元素即為表達(dá)式的值。

算法實(shí)現(xiàn):

/**
 * 算術(shù)表達(dá)式求值。
 * 3 + 4 * 12 結(jié)果為51
 * @author whf
 *
 */
public class EvaluateExpression {
 // 運(yùn)算符優(yōu)先級(jí)關(guān)系表
 private Map<String, Map<String, String>> priorityMap = new HashMap<String, Map<String, String>>();
 private LinkedStack<String> optStack = new LinkedStack<String>();
 // 運(yùn)算符棧
 private LinkedStack<Double> numStack = new LinkedStack<Double>();
 // 操作數(shù)棧
 /**
  * 計(jì)算表達(dá)式
  * @param exp 四則運(yùn)算表達(dá)式, 每個(gè)符號(hào)必須以空格分隔
  * @return
  */
 public double calcualte(String exp) {
  StringTokenizer st = new StringTokenizer(exp);
  while (st.hasMoreTokens()) {
   String token = st.nextToken();
   process(token);
  }
  return numStack.pop();
 }
 /**
  * 讀入一個(gè)符號(hào)串。
  * 如果是數(shù)字,則壓入numStack
  * 如果是運(yùn)算符,則將optStack棧頂元素與該運(yùn)算符進(jìn)行優(yōu)先級(jí)比較
  * 如果棧頂元素優(yōu)先級(jí)低,則將運(yùn)算符壓入optStack棧,如果相同,則彈出左括號(hào),如果高,則取出2個(gè)數(shù)字,取出一個(gè)運(yùn)算符執(zhí)行計(jì)算,然后將結(jié)果壓入numStack棧中
  * @param token
  */
 private void process(String token) {
  while (false == "#".equals(optStack.getTop()) || false == token.equals("#")) {
   // token is numeric
   if (true == isNumber(token)) {
        numStack.push(Double.parseDouble(token));
        break;
        // token is operator
   } else {
        String priority = priority(optStack.getTop(), token);
        if ("<".equals(priority)) {
         optStack.push(token);
         break;
        } else if ("=".equals(priority)) {
         optStack.pop();
         break;
        } else {
          double res = calculate(optStack.pop(), numStack.pop(), numStack.pop());
          numStack.push(res);
        }
   }
  }
 }
 /**
  * 執(zhí)行四則運(yùn)算
  * @param opt
  * @param n1
  * @param n2
  * @return
  */
 private double calculate(String opt, double n1, double n2) {
  if ("+".equals(opt)) {
   return n2 + n1;
  } else if ("-".equals(opt)) {
   return n2 - n1;
  } else if ("*".equals(opt)) {
   return n2 * n1;
  } else if ("/".equals(opt)) {
   return n2 / n1;
  } else {
   throw new RuntimeException("unsupported operator:" + opt);
  }
 }
 /**
  * 檢查一個(gè)String是否為數(shù)字
  * @param token
  * @return
  */
 private boolean isNumber(String token) {
  int LEN = token.length();
  for (int ix = 0 ; ix < LEN ; ++ix) {
   char ch = token.charAt(ix);
   // 跳過(guò)小數(shù)點(diǎn)
   if (ch == '.') {
    continue;
   }
   if (false == isNumber(ch)) {
    return false;
   }
  }
  return true;
 }
 /**
  * 檢查一個(gè)字符是否為數(shù)字
  * @param ch
  * @return
  */
 private boolean isNumber(char ch) {
  if (ch >= '0' && ch <= '9') {
   return true;
  }
  return false;
 }
 /**
  * 查表得到op1和op2的優(yōu)先級(jí)
  * @param op1 運(yùn)算符1
  * @param op2 運(yùn)算符2
  * @return ">", "<" 或 "="
  */
 public String priority(String op1, String op2) {
  return priorityMap.get(op1).get(op2);
 }
 /**
  * 構(gòu)造方法,初始化優(yōu)先級(jí)表
  */
 public EvaluateExpression() {
  // initialize stack
  optStack.push("#");
  // initialize priority table
  // +
  Map<String, String> subMap = new HashMap<String, String>();
  subMap.put("+", ">");
  subMap.put("-", ">");
  subMap.put("*", "<");
  subMap.put("/", "<");
  subMap.put("(", "<");
  subMap.put(")", ">");
  subMap.put("#", ">");
  priorityMap.put("+", subMap);
  // -
  subMap = new HashMap<String, String>();
  subMap.put("+", ">");
  subMap.put("-", ">");
  subMap.put("*", "<");
  subMap.put("/", "<");
  subMap.put("(", "<");
  subMap.put(")", ">");
  subMap.put("#", ">");
  priorityMap.put("-", subMap);
  // *
  subMap = new HashMap<String, String>();
  subMap.put("+", ">");
  subMap.put("-", ">");
  subMap.put("*", ">");
  subMap.put("/", ">");
  subMap.put("(", "<");
  subMap.put(")", ">");
  subMap.put("#", ">");
  priorityMap.put("*", subMap);
  // /
  subMap = new HashMap<String, String>();
  subMap.put("+", ">");
  subMap.put("-", ">");
  subMap.put("*", ">");
  subMap.put("/", ">");
  subMap.put("(", "<");
  subMap.put(")", ">");
  subMap.put("#", ">");
  priorityMap.put("/", subMap);
  // (
  subMap = new HashMap<String, String>();
  subMap.put("+", "<");
  subMap.put("-", "<");
  subMap.put("*", "<");
  subMap.put("/", "<");
  subMap.put("(", "<");
  subMap.put(")", "=");
  //subMap.put("#", ">");
  priorityMap.put("(", subMap);
  // )
  subMap = new HashMap<String, String>();
  subMap.put("+", ">");
  subMap.put("-", ">");
  subMap.put("*", ">");
  subMap.put("/", ">");
  //subMap.put("(", "<");
  subMap.put(")", ">");
  subMap.put("#", ">");
  priorityMap.put(")", subMap);
  // #
  subMap = new HashMap<String, String>();
  subMap.put("+", "<");
  subMap.put("-", "<");
  subMap.put("*", "<");
  subMap.put("/", "<");
  subMap.put("(", "<");
  //subMap.put(")", ">");
  subMap.put("#", "=");
  priorityMap.put("#", subMap);
 }
}

程序測(cè)試:

String exp = "4 * ( 10 + 2 ) + 1 #";
EvaluateExpression ee = new EvaluateExpression();
out.println(ee.calcualte(exp));

運(yùn)行結(jié)果為 49。

希望本文所述對(duì)大家的C++程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • CRC校驗(yàn)原理及其C語(yǔ)言實(shí)現(xiàn)詳解

    CRC校驗(yàn)原理及其C語(yǔ)言實(shí)現(xiàn)詳解

    循環(huán)冗余校驗(yàn)(Cyclic?Redundancy?Check,?CRC)是一種根據(jù)網(wǎng)絡(luò)數(shù)據(jù)包或計(jì)算機(jī)文件等數(shù)據(jù)產(chǎn)生簡(jiǎn)短固定位數(shù)校驗(yàn)碼的一種信道編碼技術(shù)。本文主要介紹了CRC校驗(yàn)原理及其C語(yǔ)言實(shí)現(xiàn),感興趣的可以了解一下
    2023-03-03
  • C++之vector容器的的聲明初始化和增刪改查

    C++之vector容器的的聲明初始化和增刪改查

    這篇文章主要給大家介紹了關(guān)于C++vector容器的的聲明初始化和增刪改查的相關(guān)資料,向量(Vector)是一個(gè)封裝了動(dòng)態(tài)大小數(shù)組的順序容器(Sequence Container),跟任意其它類(lèi)型容器一樣,它能夠存放各種類(lèi)型的對(duì)象,需要的朋友可以參考下
    2021-07-07
  • Qt自定義控件實(shí)現(xiàn)圓圈加載進(jìn)度條

    Qt自定義控件實(shí)現(xiàn)圓圈加載進(jìn)度條

    這篇文章主要為大家詳細(xì)介紹了Qt自定義控件實(shí)現(xiàn)圓圈加載進(jìn)度條,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C++實(shí)現(xiàn)兩個(gè)有序數(shù)組的合并

    C++實(shí)現(xiàn)兩個(gè)有序數(shù)組的合并

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)兩個(gè)有序數(shù)組的合并,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • c++利用vector創(chuàng)建二維數(shù)組的幾種方法總結(jié)

    c++利用vector創(chuàng)建二維數(shù)組的幾種方法總結(jié)

    這篇文章主要介紹了c++利用vector創(chuàng)建二維數(shù)組的幾種方法總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 全面了解結(jié)構(gòu)體、聯(lián)合體和枚舉類(lèi)型

    全面了解結(jié)構(gòu)體、聯(lián)合體和枚舉類(lèi)型

    下面小編就為大家?guī)?lái)一篇全面了解結(jié)構(gòu)體、聯(lián)合體和枚舉類(lèi)型。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-07-07
  • C/C++調(diào)用Fortran的DLL的操作過(guò)程

    C/C++調(diào)用Fortran的DLL的操作過(guò)程

    這篇文章主要介紹了C/C++調(diào)用Fortran的DLL,本文以一個(gè)簡(jiǎn)單的加法器為例,通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • C++ Qt繪制時(shí)鐘界面

    C++ Qt繪制時(shí)鐘界面

    大家好,本篇文章主要講的是C++ Qt繪制時(shí)鐘界面,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • 詳談C++的內(nèi)存泄漏問(wèn)題

    詳談C++的內(nèi)存泄漏問(wèn)題

    下面小編就為大家?guī)?lái)一篇詳談C++的內(nèi)存泄漏問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • C++ 基類(lèi)指針和子類(lèi)指針相互賦值的實(shí)現(xiàn)方法

    C++ 基類(lèi)指針和子類(lèi)指針相互賦值的實(shí)現(xiàn)方法

    下面小編就為大家?guī)?lái)一篇C++ 基類(lèi)指針和子類(lèi)指針相互賦值的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-12-12

最新評(píng)論