亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? strexpression.java

?? 計算字符串表達式的計算引擎,可以是任意復雜的字符串表達式
?? JAVA
?? 第 1 頁 / 共 2 頁
字號:
package expression;

import java.util.*;
import expression.DataInvalidException;
import expression.SOperator;
import expression.DOperator;

/**
 * <p>計算字符串表達式的值</p>
 * Vesion 1.0功能:
 * <p>Description:這個程序演示了如何計算字符串表達式的值,為了將問題簡化,在這我
 * 只是計算符號格式要求的字符串表達式的值,也就是說不做數據合法性檢測。你在測試
 * 的時候務必保證表達式正確.看上去應該是這個樣子3+2*4+1-5.
 * 字符串中的數據必須是個合法的表達式,而且表達式中的運算符號只能是+ - * / ,
 * 數字只能是0123456789 ,容許有點”.”號 ,允許操作符和運算數之間有空格
 * </p>
 *
 * Vesion 2.0 功能
 * 引入了括號運算符
 *
 * Vesion 3.0 功能
 * 支持JAVA中所有算術運算,而且允許用戶自定義運算符號.
 * <p>Copyright: Copyright (c) 2002</p>
 * <p>Company: 廣州同望科技軟件公司 </p>
 * @author 黃云輝
 * @version 2.0
 * @history:
 * 2002 -8 -11 上午 : 完成了字符串表達式的計算。不支持括號運算符
 * 2002 -8 -11 晚上 : 支持括號運算符.現在表達式可以是這個樣子(3+4)*2+2*(3+3)
 * 2002 -8 -13 上午 : 支持JAVA中所有算術運算,而且允許用戶自定義運算符號.
 *
 *為了便于問題的闡述,在此我引入3個概念
 *基本運算因子
 *    不包括括號的合法字符串表達式(不管它多么復雜)就叫做基本運算因子。比如:
 *    30*20,20,30*3+20,log10+2^3,9*3*3/3+3+34*300/3  都是一個基本運算因子.
 *基本運算因子具有這樣一條性質1:
 *    基本運算因子做任何運算后所得結果還是一個基本運算因子.
 *基本運算因子規約
 *    將多個基本運算因子化成一個基本運算因子的過程叫基本運算因子規約。
 *字符串表達式
 *    字符串表達式是“左括號(”,基本運算因子的,算術運算符和“右括號)”的集合體.
 * 字符串表達式的性質2:
 *  1:合法字符串表達式中的“(”,“)”總是成隊出現的(要么一個都沒有,要么雙雙“飛“,呵呵)
 *  2:最右的左括號相匹配的右括號離它最近.(近水樓臺先得月)
 *
 *下面我們來看看一個合法字符串的基本形態:
 *  ( (基本運算因子1)* 基本運算因子2)+基本運算因子3
 *  由性質1和性質2我們可以知道:
 *  我們可以采用一個遞歸函數將字符串表達式中的括號由里往外一層層“剝”掉,每剝
 *  掉一層都要進行一次基本因子規約。所有括號都“剝”光的時候也就是字符串表達式計
 *  算的最后一步——計算基本運算因子的結果.
 *  所以我們所要做的最重要的事就是計算基本運算因子的結果.
 *
 *  基本因子如何計算,請看下文。
 */

//---------------------------------------------------------------------
//說明: 用可以通過定義SOperatro/DOperator的實現類,并調用StringExpression
//中的操作符注冊方法: registryOp進行注冊,可以在字符串表達式中出現自定義
//操作符號. 自定義操作符號必須滿足以下條件:
//   1: 必須是合法的標識符號
//   2: 不能包括這些符號 0,1,2,3,4,5,6,7,8,9,.,E,PI
//------------------------------------------------------------------------

/**
 *@decription:計算字符串表達式的值,容許帶括號.
 *
 * 現在我門來看看如何實現括號運算符號
 * 先讓我們看個帶括號的字符串表達式:   ( ( ( 3+4 ) * 3 + 2 ) *4+3 ) *2
 * 兄臺,有沒有發現:
 *               1:“(”和“)”是成隊出現的,都是n個(在這n=3)
 *               2:  可以看出:他們伴總是離自己最近的(近水樓臺先得月,呵呵)
 *知道這些就好辦了,我門可以用遞歸函數將括號一層層剝掉
 *下面我給你介紹3個將會用到的字符串函數,有請:
 *int	lastIndexOf(int ch, int fromIndex)
 *Returns the index within this string of the last occurrence of the specified
 * character, searching backward starting at the specified index.
 *
 *String	substring(int beginIndex, int endIndex)
 *Returns a new string that is a substring of this string.
 *int	indexOf(String str, int fromIndex)
 *Returns the index within this string of the first occurrence of the specified
 * substring, starting at the specified index.
 *哈哈,是不是爽歪了,有了這3個函數我們要做的只是寫個很簡單的遞歸函數就可以搞定了.
 *具體實施請參看源代碼.
 */
public final class StrExpression {
  private  double result=0;
  private  Stack SourceStack = new Stack();//字符串表達式計算堆棧
  private  Stack TempStack = new Stack();


  //為了便于操作,用2個hash表來記錄操作符信息(這個程序運行效率不是問題)
  private static Hashtable op_level = new Hashtable();//操作符信息(操作符號,操作符級別)
  private static Hashtable op_class = new Hashtable();//操作符信息(操作符號,計算類)

  public StrExpression () {
      //注冊標準標準操作符號
      //第一級別運算符號注冊
      this.registryOp("n!",1,"expression.SN");    //注冊階乘運算
      this.registryOp("dao",1,"expression.SDao"); //注冊倒數運算
      this.registryOp("sin",1,"expression.SSin"); //注冊正玄運算
      this.registryOp("cos",1,"expression.SCos"); //注冊余玄運算
      this.registryOp("tan",1,"expression.STan"); //注冊正切運算
      this.registryOp("sqrt",1,"expression.SSqrt"); //注冊開方運算
      this.registryOp("log",1,"expression.SLog"); //注冊對數運算
      this.registryOp("ln",1,"expression.SLn"); //注冊e為底的對數運算
      this.registryOp("exp",1,"expression.SExp"); //注冊指數運算
      this.registryOp("pin",1,"expression.SX2"); //注冊平方運算
      this.registryOp("li",1,"expression.SX3"); //注冊立方運算

      //第二級別運算符號注冊
      this.registryOp("^",2,"expression.DPow"); //注冊立方運算
      this.registryOp("*",2,"expression.DMul");//注冊乘法運算
      this.registryOp("/",2,"expression.DDiv");//注冊除法運算
      this.registryOp("%",2,"expression.DMod");//注冊求余數運算
      //第三級別運算符號注冊
      this.registryOp("+",3,"expression.DAdd");//注冊加法運算
      this.registryOp("-",3,"expression.DDec");//注冊減法運算
  }

  /**
   * @description: 注冊操作符號信息
   * @param value String strOp 操作符
   * @param value int strLevel 操作符號級別(操作符號共分了3個級別1.2.3)
   * @param value String strClass 操作符號對應的操作類(帶上包名)
   * @return void
   * 說明: 所以有的運算符都必須注冊.
   */
    public static void registryOp(String strOp,int level,String strClass) {
     op_level.put(strOp,new Integer(level));
     op_class.put(strOp,strClass);
   }
   /**
    * 獲取某操作符的運算級別
    * @param value String strOp(操作符)
    * @return 操作符級別
    */
   private int getLevel( String strOp ) {
      String strLevel = op_level.get(strOp).toString();
      if ( strLevel == null )
        return 0;
      else
        return Integer.parseInt(strLevel);
   }
   /**
    *判斷給定字符串是否是已注冊的操作符號
    * @param value strOp 待判斷操作符號
    * @return 如果是已經注冊的操作符號,者返回true,否則返回false。
    */
   private boolean isOp(String strOp) {
     return op_level.containsKey(strOp);
   }
  /**
   * 獲取某操作符的運算類
   * @param value String strOp(操作符)
   * @return 操作符的運算類
   */
   private  String getClass( String strOp ) {
     return (String)op_class.get(strOp);
   }
  /**
   *將字符串表達式分解成運算符號和運算數,并將分解后的字符串保存到堆棧中
   * @param value String Expression: 字符串表達式
   * @return 運算數和運算符的集合。
   * 我采用這樣一種方式來分解字符串運算符號:
   * 先在各運算符前后都插入‘#’號,然后用StringTokenzier對字符串進行分解.
   * 在這我采用了一種比較偷懶的方法插入”#“號(因為這個程序都運算效率沒什么
   * 要求),具體如何插入,請看源代碼.
   * 這個方法比較難看懂.我是通過搜索strExpression來定temp的插入位置,所以有個位置
   * 差的問題.如果您有什么不明白的地方隨時可以和我聯系.
   */
  private  Stack  splitStr(String strExpression) throws DataInvalidException {
     //----------------------------------------------
     HashSet hs = new HashSet();
     hs.addAll(op_level.keySet());
     hs.add("(");
     hs.add(")");
     //運算符號集合.
     //------------------------------------------------
     Iterator i = hs.iterator();//用來遍歷運算符
     String strOp;
     StringBuffer temp = new StringBuffer(strExpression);//為了提高運算效率,引入該變量

     //----------------------------------------------------------------------------------
     //表答式最前面容許出現‘-’號(負號),可以出現多個負,但沒什么意義,所以目前程序
     //只許出現一個負號..
     String strHead = new String();//用來保存”-”號
     while(true) {//
        if ( temp.charAt(0)== '-'){
          temp.deleteCharAt(0);
          strHead +="-";
        } else break;
     }
    //----------------------------------------------------------------------------------
     if  ( temp.toString().trim().length() == 0)//只有負號的表達式
       throw new DataInvalidException("您輸入的字符串表達式,不符合格式要求,"+
                                      "導致無法計算,請檢測您的輸入表達式");

     while ( i.hasNext() ) {
       int intInsertPos=0;//'#'的插入點.
       int intIndex=0;//搜索位置
       int intLen=0;//操作符的長度
       int intDiff=0;//記錄位置差
       strOp = i.next().toString();//取出一個運算符
       intLen = strOp.length();
       strExpression = temp.toString();//temp的值會發生變化,每次插入符號前
       //要保證strExpression與temp值相同
       while(true) {
         intIndex =strExpression.indexOf(strOp,intIndex);
         if ( intIndex == -1 ) // 沒有找到.
           break;
         intInsertPos = intIndex + intDiff;//設置插入位置
         if (intIndex ==0){
           temp.insert(intInsertPos+intLen,'#');//運算符號后面插入“#”
           intDiff ++;
         }else{
           temp.insert(intInsertPos,'#');//運算符號前插入“#”
           temp.insert(intInsertPos+intLen+1,'#');//運算符號后面插入“#”
           intDiff += 2;
         }
         intIndex +=  intLen;//調整搜索位置.

         }//end while(true);
     }// end while(i .hasNext());
      strExpression = strHead +temp.toString();
    // 創建個StringTokenizer對象用來提取表達式中的運算符號.
     Stack result = new Stack();
     StringTokenizer tool = new StringTokenizer(strExpression,"# ");
     while(tool.hasMoreElements())
            result.push(tool.nextElement());
     return result;
  }

  /**
   *@decription: 獲取表達式的值.
   *@param value : 待計算的字符串表達式
   *@return : 字符串表達式的值.
   */
  public  double getValue(String value) throws DataInvalidException{
    int intIndexLeft;//最后一個“(”在字符串value 中的位置
    int intIndexRight;//第一個")"在字符串value中的位置.

    intIndexLeft = value.lastIndexOf("(");//取得左括號的索引
    if ( intIndexLeft == -1 ) {//value中不存在括號.
    try {
            result = parseValue(value);//如果當value不是個表達式時,會觸發異常
        } catch (DataInvalidException die) {
           throw die;
      }//end try -catch
    }// end if
    else {
      intIndexRight = value.indexOf(")",intIndexLeft);//獲取與左括號相匹配的右括號。
      //將表達式分成 左 中 右三串
      String strLeft = value.substring(0,intIndexLeft);//取左串
      String strTemp = value.substring(intIndexLeft+1,intIndexRight);//取中串
      double dblTemp;
      try {
         dblTemp = parseValue(strTemp);//計算中串的值.
      }catch(DataInvalidException die){
        throw die;
      }
      String strMid = new Double(dblTemp).toString();//得到新的中串
      String strRight= value.substring(intIndexRight+1);//獲取右串
      value = strLeft + strMid + strRight;//重新組合字符串表達式 .
      getValue(value);//遞歸計算.
    } //end else
    return result;
  }//end getValue

    /**
     *@description:計算運算因子的值
     *@param value : 運算因子
     *@return: 運算因子的值
     */
    private  double parseValue( String value )throws DataInvalidException{

       this.SourceStack.clear();
       this.TempStack.clear();
      /*1:數據合法性檢測
       *如果數據是非法的,則拋出DataInvalidException異常,為了
       *簡化問題,在這不做數據合法性檢測.如果您是做正式產品,這步不能省.
       */

      /*2:數據分解
       *將字符串的表達式分解成運算符號,和運算數的集合體,并將這些數據壓入SourceStack堆棧中.
       *如果輸入串是"32+33*14-1”那么分解后將會是"32","+","33"*","14","-","1"這個樣子。
       *
       *分解方法:
       *為了便于說明問題,假設輸入字符串是-32+2*4+3-1
       *我門的任務就是將“-32+2*4+3-1“分解成多個字符串: “-32”,”+”,”2”,”*”,”4”,”+”,+”3”,”-“,”1”.
       *兄弟門有沒有發現:沒個運算都是夾在2個數的中間,要是我們在運算符的前面和后面都插入字符“,”,就可以將數字
       *和運算符號分開.我門來看看插入符號’,’后字符串的形態: -32,+,2,*,4,*,3,-,1.
       *分解這類字符串是StringTokenizer的拿手把戲了,只要將分解標志設為”,”就可以搞定了.
       */
       try{
            SourceStack.addAll(this.splitStr(value));
       }catch (DataInvalidException die) {
         throw die;
       }
       //消除第1級別的運算符
        delLevel1();
       //將TempStack中的數據挪到SourceStack中,并清除TempStack中內容。這樣做沒什么特別
       //的原因,只是為了沿用上版的某些功能.
       SourceStack.addAll((Collection)TempStack.clone());
       TempStack.clear();

       //如果堆棧中只有一個數據則認為是一個合法數據,否則觸發異常.
       if (SourceStack.size() == 1) {
         try {
            return Double.parseDouble(SourceStack.pop().toString());
         }catch (Exception e) {
           throw new DataInvalidException("您輸入的字符串表達式,不符合格式要求,"+
                                          "導致無法計算,請檢測您的輸入表達式");
         }
       }
        //第2層處理,消除第2級別的運算符號
        delLevel2();
       //第三層處理,消除第三級別的運算符號
        Collections.reverse(TempStack);
        return delLevel3();//返回基本運算因子的運算結果 .

    }// end StringToValue

    //第1層處理,消除第1級別的運算符號
    private  void delLevel1() {
      //第1層處理,消除第1級別的運算符號
       String strTemp;//用來保存從SourceStack中彈出來的字符串.

       int intSize = SourceStack.size() ;
       for( int i=0 ;i< intSize;i++) {
          strTemp = (String)SourceStack.pop();
          if ( isOp(strTemp) ) {//如果是運算符號
          int intLevel = this.getLevel(strTemp);//獲取運算級別
          if ( intLevel==1) {//
              Object objX = TempStack.pop();//取出運算數
              String strClass = getClass(strTemp);// 獲取類包路徑
              try {
                 Class clsCalculate = Class.forName(strClass);
                 SOperator cal = (SOperator)clsCalculate.newInstance();
                 TempStack.push(cal.calculate(objX));
              }catch(Exception e) {
                e.printStackTrace();
              }//end try-catch
            }//if (intLevel==1)
            if ( intLevel==3 ||
                 intLevel==2 ) {//將2,3級別運算符號進行壓棧處理

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产片一区二区| 亚洲精品视频一区二区| 中文字幕av一区二区三区免费看| 亚洲你懂的在线视频| 美女www一区二区| 色系网站成人免费| 久久久久久99精品| 蜜臀av性久久久久av蜜臀妖精| 91免费国产在线观看| 国产蜜臀av在线一区二区三区| 午夜国产精品影院在线观看| 97久久超碰国产精品| 亚洲一区精品在线| 丁香五精品蜜臀久久久久99网站 | 亚洲蜜臀av乱码久久精品| 激情久久五月天| 欧美一级生活片| 亚洲mv大片欧洲mv大片精品| 99国产精品国产精品久久| 久久九九全国免费| 国模冰冰炮一区二区| 日韩亚洲国产中文字幕欧美| 视频在线在亚洲| 欧美色视频在线| 亚洲午夜在线观看视频在线| 一本久道中文字幕精品亚洲嫩| 国产精品青草久久| voyeur盗摄精品| 国产精品免费久久| 99久久综合国产精品| 亚洲欧洲av在线| 91尤物视频在线观看| 国产精品久久久久久久久久久免费看| 国产成人免费视| 日本一区二区三区电影| 成人一级片网址| 中文字幕中文字幕在线一区 | 色婷婷av一区| 一区二区三区欧美激情| 欧美日韩综合不卡| 国产成人av网站| 亚洲国产精品t66y| 91免费版pro下载短视频| 亚洲天堂久久久久久久| 91视频在线观看| 亚洲成人免费在线| 欧美一级二级在线观看| 国产在线视视频有精品| 国产精品女同互慰在线看| 99国产精品国产精品久久| 亚洲午夜精品17c| 欧美一级高清大全免费观看| 国产在线精品一区二区三区不卡| 欧美国产禁国产网站cc| 日本大香伊一区二区三区| 丝袜美腿亚洲色图| 久久久国产精品午夜一区ai换脸| 99久久99久久精品免费观看| 亚洲国产成人va在线观看天堂| 日韩一区二区高清| 粉嫩13p一区二区三区| 玉米视频成人免费看| 欧美va亚洲va| 99精品一区二区| 美国欧美日韩国产在线播放 | 欧美怡红院视频| 蜜桃91丨九色丨蝌蚪91桃色| 日本一区二区三区在线不卡| 欧美视频日韩视频| 精品午夜一区二区三区在线观看| 一区在线中文字幕| 日韩一区二区三区四区五区六区| 成人福利在线看| 麻豆成人av在线| 一区二区三区欧美激情| 国产视频一区在线观看| 欧美日韩精品一区二区在线播放 | 99视频超级精品| 久久99热国产| 一区二区三区免费看视频| 久久嫩草精品久久久精品一| 欧美日韩国产首页在线观看| 成人性生交大片免费看在线播放 | 91免费国产在线观看| 国内精品久久久久影院一蜜桃| 一区二区三区**美女毛片| 久久久久亚洲综合| 91精品欧美综合在线观看最新| 91视频观看免费| 成人午夜电影久久影院| 久久99精品网久久| 日韩一区精品字幕| 亚洲国产精品精华液网站 | 久久久久久久久久久电影| 欧美电影一区二区| 日本高清不卡在线观看| 丰满白嫩尤物一区二区| 精品亚洲国产成人av制服丝袜 | 久久精品视频网| 日韩欧美一区二区不卡| 欧美日韩在线直播| 欧美在线观看视频在线| 91伊人久久大香线蕉| www.一区二区| kk眼镜猥琐国模调教系列一区二区| 韩日精品视频一区| 久久丁香综合五月国产三级网站| 午夜精品国产更新| 亚洲高清免费视频| 亚洲电影中文字幕在线观看| 亚洲女人****多毛耸耸8| 最好看的中文字幕久久| 国产精品动漫网站| 亚洲男人的天堂在线aⅴ视频| 亚洲欧洲成人精品av97| 综合在线观看色| 亚洲精品视频自拍| 一卡二卡三卡日韩欧美| 亚洲国产精品久久不卡毛片| 亚洲成人福利片| 日韩国产欧美在线观看| 老司机免费视频一区二区| 久久成人羞羞网站| 国产在线不卡视频| youjizz久久| 91黄色在线观看| 666欧美在线视频| 日韩美女天天操| 国产欧美日产一区| 亚洲日本在线视频观看| 亚洲无线码一区二区三区| 日韩中文字幕亚洲一区二区va在线| 日韩国产在线一| 国产精品一区在线| 99国产精品久久久久| 欧美日韩在线观看一区二区 | 欧美zozozo| 日本一区二区动态图| 亚洲久草在线视频| 日韩av中文在线观看| 国产一区二区三区四区在线观看| 风间由美中文字幕在线看视频国产欧美 | 国产99精品国产| 在线视频亚洲一区| 精品少妇一区二区三区在线播放 | 国产精品一品二品| 91婷婷韩国欧美一区二区| 欧美精品tushy高清| 久久久精品影视| 亚洲国产综合色| 国产精品一区二区三区网站| 91毛片在线观看| 欧美精品一区二区三区蜜臀| 亚洲欧美日韩人成在线播放| 蜜桃传媒麻豆第一区在线观看| 国产91丝袜在线观看| 欧美日韩国产高清一区二区三区 | 国产欧美日韩三级| 亚洲影院久久精品| 国产精品1区二区.| 欧美日韩电影一区| 欧美激情在线免费观看| 日韩国产精品久久| 92精品国产成人观看免费| 精品久久久久av影院| 夜夜嗨av一区二区三区四季av| 老司机午夜精品99久久| 欧美色窝79yyyycom| 国产精品久久久久久久久久久免费看| 热久久一区二区| 日本韩国精品一区二区在线观看| 久久精品在线观看| 免费在线观看一区二区三区| 在线欧美一区二区| 国产精品久久久久久户外露出 | 欧美电视剧免费全集观看| 亚洲尤物在线视频观看| 成人av在线播放网址| 精品91自产拍在线观看一区| 图片区小说区区亚洲影院| 色哟哟一区二区在线观看| 欧美激情一区二区| 国产一区二区成人久久免费影院 | 日韩黄色免费电影| 欧美专区日韩专区| 亚洲精品视频免费看| 成人成人成人在线视频| 国产欧美日韩一区二区三区在线观看| 美国三级日本三级久久99| 69精品人人人人| 日韩经典中文字幕一区| 欧美综合一区二区三区| 亚洲天堂免费看| 色呦呦一区二区三区| 亚洲日本va在线观看| 91色porny蝌蚪| 亚洲同性gay激情无套| 一本一本久久a久久精品综合麻豆| 欧美国产精品中文字幕| 成人午夜精品在线|