Luben Park

          Java Ben 成長之路

          快速精確的對(duì)數(shù)學(xué)表達(dá)式求值

          快速精確的對(duì)數(shù)學(xué)表達(dá)式求值 英文原文
          內(nèi)容:
          表達(dá)式求值的經(jīng)典算法
          W3Eval:一種新的方法
          結(jié)論
          參考資料
          關(guān)于作者
          對(duì)本文的評(píng)價(jià)
          相關(guān)內(nèi)容:
          教程:Building a Java applet
          更多 dW Java 參考資料
          使用這個(gè)方便的 applet ,您就能一步一步的計(jì)算數(shù)學(xué)表達(dá)式了 Nikola Stepan (nikola.stepan@vz.tel.hr)
          軟件工程師,ABIT Ltd.
          2001 年 9 月
          對(duì)于未經(jīng)訓(xùn)練的用戶來說,計(jì)算機(jī)科學(xué)領(lǐng)域中數(shù)學(xué)表達(dá)式求值的傳統(tǒng)方法即不順手又難以使用;軟件工程師 Nikola.Stepan 旨在改變這些傳統(tǒng)方法。他的 applet W3Eval 對(duì)表達(dá)式求值與您用紙筆計(jì)算的一系列步驟完全一致,但更快并且沒有錯(cuò)誤。請(qǐng)往下讀,了解這一挑戰(zhàn) — 人類易讀的數(shù)學(xué)到 Java 代碼的轉(zhuǎn)換。
          還記得在您的第一臺(tái)科學(xué)計(jì)算器上用逆波蘭表示法奮斗的經(jīng)歷嗎?W3Eval applet 無法讓您可信賴的 HP-41 更易用,正如它的名稱所暗示 — 一個(gè)只能運(yùn)行于 Web 的表達(dá)式求值程序。但它的確提供了一種方法 — 人類更易于遵循的對(duì)表達(dá)式一步一步的求值。

          W3Eval 的方法與傳統(tǒng)計(jì)算器不同,卻和人類的計(jì)算方式一致。當(dāng)您用傳統(tǒng)的計(jì)算器計(jì)算時(shí),每輸入一個(gè)新數(shù),前一個(gè)數(shù)就看不到了。如果在輸入一個(gè)長表達(dá)式中出了錯(cuò),就得全部重來。有了 W3Eval,您就能看到參與計(jì)算的所有東西,還能輕松的編輯表達(dá)式。它獨(dú)特的能力(一步一步的對(duì)表達(dá)式求值)非常容易實(shí)現(xiàn),因?yàn)橛脩裟芸吹角笾档拿恳徊?,包括臨時(shí)結(jié)果。

          本文將讓您從頭至尾認(rèn)識(shí) W3Eval 功能性的要點(diǎn);您將看到一些用于表達(dá)式求值的代碼。不過,我們還是先看看表達(dá)式求值的經(jīng)典算法,這樣您就會(huì)明白 W3Eval 方法的差異究竟有多少。

          表達(dá)式求值的經(jīng)典算法
          編寫代碼對(duì)算術(shù)表達(dá)式求值的經(jīng)典方法由 Donald Knuth 描述于 1962 年(請(qǐng)參閱參考資料)。Knuth 將此概括為三個(gè)步驟:
          • 對(duì)中綴表達(dá)式進(jìn)行語法分析
          • 中綴表達(dá)式到后綴表達(dá)式的轉(zhuǎn)換
          • 對(duì)后綴表達(dá)式求值
          注意到我們談到的這個(gè)經(jīng)典算法有些簡化:算術(shù)表達(dá)式只包含操作數(shù)、二元操作符和一種括號(hào)。此外,對(duì)于每個(gè)操作數(shù)和操作符,只用單個(gè)字符表示,使語法分析直觀。

          表達(dá)式表示法
          算術(shù)表達(dá)式中最常見的表示法形式有中綴、前綴后綴表示法。中綴表示法是書寫表達(dá)式的常見方式,而前綴和后綴表示法主要用于計(jì)算機(jī)科學(xué)領(lǐng)域。

          中綴表示法
          中綴表示法是算術(shù)表達(dá)式的常規(guī)表示法。稱它為中綴表示法是因?yàn)槊總€(gè)操作符都位于其操作數(shù)的中間,這種表示法只適用于操作符恰好對(duì)應(yīng)兩個(gè)操作數(shù)的時(shí)候(在操作符是二元操作符如加、減、乘、除以及取模的情況下)。對(duì)以中綴表示法書寫的表達(dá)式進(jìn)行語法分析時(shí),需要用括號(hào)和優(yōu)先規(guī)則排除多義性。



          Syntax: operand1 operator operand2Example: (A+B)*C-D/(E+F)
          前綴表示法
          前綴表示法中,操作符寫在操作數(shù)的前面。這種表示法經(jīng)常用于計(jì)算機(jī)科學(xué),特別是編譯器設(shè)計(jì)方面。為紀(jì)念其發(fā)明家 — Jan Lukasiewicz(請(qǐng)參閱參考資料),這種表示法也稱波蘭表示法。



          Syntax : operator operand1 operand2Example : -*+ABC/D+EF
          后綴表示法
          在后綴表示法中,操作符位于操作數(shù)后面。后綴表示法也稱逆波蘭表示法(reverse Polish notation,RPN),因其使表達(dá)式求值變得輕松,所以被普遍使用。



          Syntax : operand1 operand2 operatorExample : AB+C*DEF+/-
          前綴和后綴表示法有三項(xiàng)公共特征:
          • 操作數(shù)的順序與等價(jià)的中綴表達(dá)式中操作數(shù)的順序一致
          • 不需要括號(hào)
          • 操作符的優(yōu)先級(jí)不相關(guān)
          中綴表達(dá)式到后綴表達(dá)式的轉(zhuǎn)換
          要把表達(dá)式從中綴表達(dá)式的形式轉(zhuǎn)換成用后綴表示法表示的等價(jià)表達(dá)式,必須了解操作符的優(yōu)先級(jí)和結(jié)合性。優(yōu)先級(jí)或者說操作符的強(qiáng)度決定求值順序;優(yōu)先級(jí)高的操作符比優(yōu)先級(jí)低的操作符先求值。 如果所有操作符優(yōu)先級(jí)一樣,那么求值順序就取決于它們的結(jié)合性。操作符的結(jié)合性定義了相同優(yōu)先級(jí)操作符組合的順序(從右至左或從左至右)。



          Left associativity : A+B+C = (A+B)+CRight associativity : A^B^C = A^(B^C)
          轉(zhuǎn)換過程包括用下面的算法讀入中綴表達(dá)式的操作數(shù)、操作符和括號(hào):
          1. 初始化一個(gè)空堆棧,將結(jié)果字符串變量置空。
          2. 從左到右讀入中綴表達(dá)式,每次一個(gè)字符。
          3. 如果字符是操作數(shù),將它添加到結(jié)果字符串。
          4. 如果字符是個(gè)操作符,彈出(pop)操作符,直至遇見開括號(hào)(opening parenthesis)、優(yōu)先級(jí)較低的操作符或者同一優(yōu)先級(jí)的右結(jié)合符號(hào)。把這個(gè)操作符壓入(push)堆棧。
          5. 如果字符是個(gè)開括號(hào),把它壓入堆棧。
          6. 如果字符是個(gè)閉括號(hào)(closing parenthesis),在遇見開括號(hào)前,彈出所有操作符,然后把它們添加到結(jié)果字符串。
          7. 如果到達(dá)輸入字符串的末尾,彈出所有操作符并添加到結(jié)果字符串。
          后綴表達(dá)式求值
          對(duì)后綴表達(dá)式求值比直接對(duì)中綴表達(dá)式求值簡單。在后綴表達(dá)式中,不需要括號(hào),而且操作符的優(yōu)先級(jí)也不再起作用了。您可以用如下算法對(duì)后綴表達(dá)式求值:
          1. 初始化一個(gè)空堆棧
          2. 從左到右讀入后綴表達(dá)式
          3. 如果字符是一個(gè)操作數(shù),把它壓入堆棧。
          4. 如果字符是個(gè)操作符,彈出兩個(gè)操作數(shù),執(zhí)行恰當(dāng)操作,然后把結(jié)果壓入堆棧。如果您不能夠彈出兩個(gè)操作數(shù),后綴表達(dá)式的語法就不正確。
          5. 到后綴表達(dá)式末尾,從堆棧中彈出結(jié)果。若后綴表達(dá)式格式正確,那么堆棧應(yīng)該為空。
          W3Eval:一種新的方法
          W3Eval 的方法與上面概括的經(jīng)典算法不同。不是把中綴表達(dá)式轉(zhuǎn)換為后綴表示法;恰恰相反,它對(duì)中綴表達(dá)式直接求值。這種方法比傳統(tǒng)方法稍微復(fù)雜了些,但它支持一步一步的求值,在執(zhí)行時(shí)您能看到每一步。求值過程類似于手工計(jì)算:如果表達(dá)式中包含括號(hào),先求嵌套最深的括號(hào)對(duì)中的子表達(dá)式的值。所有括號(hào)內(nèi)的子表達(dá)式都求值完畢后,表達(dá)式的其它部分再求值。

          求值過程分為三個(gè)步驟:
          1. 表達(dá)式語法分析
          2. 表達(dá)式檢查
          3. 一步一步的求值
          表達(dá)式語法分析
          W3Eval 的數(shù)學(xué)表達(dá)式由數(shù)字、變量、操作符、函數(shù)和括號(hào)組成。除了缺省的十進(jìn)制計(jì)數(shù)制外 W3Eval 還支持二進(jìn)制、八進(jìn)制和十六進(jìn)制。這些以其它計(jì)數(shù)制計(jì)數(shù)的數(shù)必須以 # 開頭,并緊跟 b、o 或者 h 來分別表示二進(jìn)制、八進(jìn)制或十六進(jìn)制。

          W3Eval 的變量是不限長度的大寫字母和數(shù)字序列,其首字符必須是字母。W3Eval 有一些預(yù)定義的變量,不過它也支持用戶定義的變量。

          W3Eval 支持帶有固定或不定數(shù)量自變量的函數(shù)。 函數(shù)可分為以下幾組:
          • 三角函數(shù)(sin、cos、tan、cot、sec、csc)
          • 反三角函數(shù)(asin、acos、atan、atan2、acot、asec、acsc)
          • 雙曲線函數(shù)(sinh、cosh、tanh、coth、sech、csch)
          • 反雙曲線函數(shù)(asinh、acosh、atanh、acoth、asech、acsch)
          • 指數(shù)函數(shù)(log、log2、log10、exp、exp2、exp10、sqrt、cur)
          • 組合學(xué)函數(shù)(Combinatoric)(comb、combr、perm、permr、var、varr)
          • 統(tǒng)計(jì)函數(shù)(sum、avg、min、max、stddev、count)
          • 其它(abs、ceil、fact、floor、pow、random、rint、round、sign、frac、hypot、deg、rad、trunc、int)
          W3Eval 對(duì)表達(dá)式進(jìn)行語法分析,也就是指它識(shí)別出表達(dá)式的算術(shù)成分,并將它們轉(zhuǎn)化成語言符號(hào)(token),然后把它們放入向量。表達(dá)式一旦處于這種狀態(tài),就為下面兩步做好了準(zhǔn)備:表達(dá)式檢查和求值。

          W3Eval 的符號(hào)(token)是算術(shù)表達(dá)式的組成部分;記號(hào)(mark) 是獨(dú)立的字符, 由 applet 使用,作為識(shí)別各種符號(hào)的內(nèi)部標(biāo)志。每種符號(hào)有唯一的 mark 與之對(duì)應(yīng)。W3Eval 的表達(dá)式由表 1 所示的符號(hào)組成。

          表 1. W3Eval 的符號(hào)
          Token Mark
          十進(jìn)制數(shù) Double
          二進(jìn)制數(shù) String
          十六進(jìn)制數(shù) String
          八進(jìn)制數(shù) String
          變量 Variable
          函數(shù) Function
          操作符 Operator
          開括號(hào) String
          閉括號(hào) String
          逗號(hào) String


          用以表示函數(shù)、操作符和變量類的定義如清單 1 所示:

          清單 1. Function、Operator 和 Variable 類的定義


          public class Function { public String function; public int number_of_arguments; public Function( String function, int number_of_arguments ) { this.function=function; this.number_of_arguments=number_of_arguments; } public String toString() { return function; } }public class Operator { public String operator; public byte priority; public Operator( String operator, byte priority ) { this.operator=operator; this.priority=priority; } public String toString() { return operator; } }public class Variable { public String variable; public double value; public Variable( String variable, double value ) { this.variable=variable; this.value=value; } public String toString() { return variable; } }
          Token 類如清單 2 所示。

          清單 2. Token 類


          public class Token { public Object token; public char mark; public int position; public int length; public Token ( Object token, char mark, int position, int length ) { this.token=token; this.mark=mark; this.position=position; this.length=length; } public String toString() { return token.toString()+" ; "+mark+" ; "+position+" ; "+length+""; } }
          表達(dá)式檢查
          檢查正規(guī)表達(dá)式正確性的所有代碼都在一個(gè)獨(dú)立的類中。詳細(xì)的表達(dá)式檢查能夠確定錯(cuò)誤確切的類型和位置。 錯(cuò)誤檢查有七類:

          括號(hào)檢查。W3Eval 的表達(dá)式可以包含三種括號(hào):標(biāo)準(zhǔn)圓括號(hào)、方括號(hào)和花括號(hào)。如果表達(dá)式包含相同數(shù)量的開括號(hào)和閉括號(hào),并且每個(gè)開括號(hào)與一個(gè)相應(yīng)的同種閉括號(hào)相匹配,則表達(dá)式的括號(hào)語法正確。三種括號(hào)在語義上等價(jià),如下面的代碼段所示。

          清單 3. 三種括號(hào)


          import java.util.Stack;public class Parentheses_check { public static boolean is_open_parenthesis( char c ) { if ( c=='(' || c=='[' || c=='{' ) return true; else return false; } public static boolean is_closed_parenthesis( char c ) { if ( c==')' || c==']' || c=='}' ) return true; else return false; } private static boolean parentheses_match( char open, char closed ) { if ( open=='(' && closed==')' ) return true; else if ( open=='[' && closed==']' ) return true; else if ( open=='{' && closed=='}' ) return true; else return false; } public static boolean parentheses_valid( String exp ) { Stack s = new Stack(); int i; char current_char; Character c; char c1; boolean ret=true; for ( i=0; i < exp.length(); i++ ) { current_char=exp.charAt( i ); if ( is_open_parenthesis( current_char ) ) { c=new Character( current_char ); s.push( c ); } else if ( is_closed_parenthesis( current_char ) ) { if ( s.isEmpty() ) { ret=false; break; } else { c=(Character)s.pop(); c1=c.charValue(); if ( !parentheses_match( c1, current_char ) ) { ret=false; break; } } } } if ( !s.isEmpty() ) ret=false; return ret; } }
          token 檢查。檢查表達(dá)式語法。確保表達(dá)式所有部分都被認(rèn)為是合法的。

          表達(dá)式開頭的檢查(請(qǐng)參閱清單 4。確保表達(dá)式從合法的符號(hào)開始。不可以用操作符、逗號(hào)或閉括號(hào)作為表達(dá)式的開始符。





          清單 4. 正確的表達(dá)式開頭的檢查


          private static boolean begin_check( Vector tokens, Range r, StringBuffer err ) { char mark; Token t; t=(Token)tokens.elementAt( 0 ); mark=t.mark; if ( mark=='P' ) err.append( Messages.begin_operator ); else if ( mark==')' ) err.append( Messages.begin_parenthesis ); else if ( mark=='Z' ) err.append ( Messages.begin_comma ); else return true; r.start=0; r.end=t.length; return false; }


          表達(dá)式末尾的檢查。確保表達(dá)式以合法符號(hào)結(jié)束。不可以用操作符、函數(shù)、逗號(hào)或開括號(hào)作為表達(dá)式結(jié)束符。

          符號(hào)序列的檢查。檢查表達(dá)式中的符號(hào)序列。在下面的表格中,若 X 軸上的符號(hào)和 Y 軸上的符號(hào)對(duì)應(yīng)的交界處用 X 作了記號(hào),則相應(yīng) X 軸上的符號(hào)可以接在 Y 軸上符號(hào)的后面。

          表 2. 合法的符號(hào)序列
          _ D B H O V F P ( ) Z
          D _ _ _ _ _ _ _
          B _ _ _ _ _ _ _
          H _ _ _ _ _ _ _
          O _ _ _ _ _ _ _
          V _ _ _ _ _ _ _
          F _ _ _ _ _ _ _ _ _
          P _ _ _
          ( _ _ _
          ) _ _ _ _ _ _ _
          Z _ _ _


          函數(shù)檢查。確保表達(dá)式中所有函數(shù)的自變量數(shù)量正確。

          逗號(hào)檢查。逗號(hào)只能用于分隔函數(shù)的自變量。若用于表達(dá)式其它地方,就不合法。

          一步一步的求值
          只有能順利通過以上概括的所有檢查的表達(dá)式,W3Eval 才求值。從而確保內(nèi)建于 W3Eval 中的前提條件不會(huì)出現(xiàn)問題。后面的算法用于單步執(zhí)行表達(dá)式求值:
          1. 找出嵌入最深的那對(duì)括號(hào)。
          2. 在這對(duì)括號(hào)中,找出優(yōu)先級(jí)最高的操作符。
          3. 若這對(duì)括號(hào)中沒有操作符:
            • 如果表達(dá)式再不包含任何其它的括號(hào),求值(過程)完成。
            • 如果表達(dá)式包含括號(hào),但不包含操作符,則存在一個(gè)函數(shù)。對(duì)函數(shù)求值,然后轉(zhuǎn)到步驟 5。
          4. 獲取操作數(shù)并執(zhí)行運(yùn)算。
          5. 從向量中除去用過的符號(hào)并在同一位置放入結(jié)果。
          6. 除去冗余括號(hào)。
          7. 將向量中剩余的符號(hào)結(jié)合到字符串并在屏幕上顯示結(jié)果。
          現(xiàn)在,我們將更為詳細(xì)的查看算法的每一步,同時(shí)查看大部分有意思的代碼片段。

          步驟 1:為避免括號(hào)的處理,W3Eval 確定哪個(gè)子表達(dá)式處于嵌套最深的那對(duì)括號(hào)中。這項(xiàng)任務(wù)需要兩步。第一步,W3Eval 必須找出第一個(gè)閉括號(hào):

          清單 5. 找出第一個(gè)閉括號(hào)


          public static int pos_first_closed_parenthesis( Vector tokens ) { Token t; for ( int i=0; i
          第二步,找出與第一步找到的閉括號(hào)相匹配的開括號(hào),如清單 6 所示。





          清單 6. 找出匹配的開括號(hào)


          public static int pos_open_parenthesis( Vector tokens, int closed_parenthesis ) { int i; Token t; i=closed_parenthesis-2; while ( i>=0 ) { t=(Token)tokens.elementAt( i ); if ( t.mark=='(' ) { return i; } i--; } return 0; }


          步驟 2:要實(shí)現(xiàn)求值的單步執(zhí)行,W3Eval 在嵌套最深的那對(duì)括號(hào)中找出優(yōu)先級(jí)最高的操作符。(操作符的優(yōu)先級(jí)已硬編碼到 applet 中;請(qǐng)參閱參考資料以獲取完整的代碼清單。)

          清單 7. 找出優(yōu)先級(jí)最高的操作符


          public static int pos_operator( Vector tokens, Range r ) { byte max_priority=Byte.MAX_VALUE; int max_pos=0; byte priority; String operator; Token t; for ( int i=r.start+2; i<=r.end-2; i++ ) { t=(Token)tokens.elementAt( i ); if ( t.mark!='P' ) continue; priority=((Operator)t.token).priority; operator=((Operator)t.token).operator; if ( priority < max_priority || ( operator.equals("^") || operator.equals("**") ) && priority == max_priority ) { max_priority=priority; max_pos=i; } } return max_pos; }
          步驟 3:如果表達(dá)式中不包含其它括號(hào),求值的過程就完成。如果表達(dá)式包含括號(hào),但不包含操作符,則存在需要求值的函數(shù)。

          清單 8. 檢查是否還有其它操作符


          ...int poz_max_op=pos_operator( tokens, range );// if there are no operatorsif ( poz_max_op==0 ) { if ( no_more_parentheses ) { return false; } else { double result; result=function_result( tokens, range.start-1 ); function_tokens_removal( tokens, range.start-1 ); t = new Token ( new Double(result), 'D', 0, 0 ); tokens.setElementAt( t, range.start-1 ); parentheses_removal( tokens, range.start-1 ); return true; } }...
          步驟 4:所有的操作符都是二元的,也就是說第一個(gè)操作數(shù)位于操作符之前,第二個(gè)操作符位于操作符之后。

          清單 9. 獲取操作數(shù)并執(zhí)行運(yùn)算


          ...double operand1, operand2;// first operand is before...t=(Token)tokens.elementAt( poz_max_op-1 );operand1=operand_value( t );// ...and second operand is after operatort=(Token)tokens.elementAt( poz_max_op+1 );operand2=operand_value( t );// operatort=(Token)tokens.elementAt( poz_max_op );String op=((Operator)t.token).operator;double result=operation_result( operand1, operand2, op );tokens.removeElementAt( poz_max_op+1 );tokens.removeElementAt( poz_max_op );t = new Token ( new Double(result), 'D', 0, 0 );tokens.setElementAt( t, poz_max_op-1 );parentheses_removal( tokens, poz_max_op-1 );...
          操作數(shù)可以是變量,還可以是十進(jìn)制、十六進(jìn)制、八進(jìn)制或二進(jìn)制數(shù)。

          清單 10. 獲取操作數(shù)


          public static double operand_value( Token t ) { if ( t.mark=='V' ) return ((Variable)t.token).value; else if ( t.mark=='D' ) return ((Double)t.token).doubleValue(); else if ( t.mark=='H' ) return base_convert( ((String)t.token).substring(2), 16 ); else if ( t.mark=='O' ) return base_convert( ((String)t.token).substring(2), 8 ); else if ( t.mark=='B' ) return base_convert( ((String)t.token).substring(2), 2 ); }
          接下來的方法將不同計(jì)數(shù)制的數(shù)轉(zhuǎn)化為十進(jìn)制的形式。

          清單 11. 將數(shù)轉(zhuǎn)化為十進(jìn)制數(shù)


          public static long base_convert( String s, int base ) { long r=0; int i, j; for ( i=s.length()-1, j=0; i>=0; i--, j++ ) r=r+digit_weight( s.charAt( i ) )*(long)Math.pow( base, j ); return r; }public static int digit_weight( char c ) { if ( Character.isDigit( c ) ) return c-48; else if ( 'A'<=c && c<='f' ) return c-55; else if ( 'a'<=c && c<='f' ) return c-87; return -1; }
          一旦確定操作數(shù)和操作符后,就可以執(zhí)行運(yùn)算了,如清單 12 所示。

          步驟 5:在這步中,W3Eval 從向量中除去用過的符號(hào)并在同一位置放入結(jié)果。對(duì)于函數(shù)求值這類情況,除去的是函數(shù)、括號(hào)、自變量和逗號(hào);而對(duì)于操作符求值這類情況而言,除去的則是操作數(shù)和操作符。

          步驟 6:在求值的這一步,W3Eval 從表達(dá)式中除去冗余括號(hào)。

          清單 13. 除去冗余括號(hào)


          private static void parentheses_removal( Vector tokens, int pos ) { if ( pos>1 &&&& ((Token)tokens.elementAt( poz-2 )).mark!='F' &&&& ((Token)tokens.elementAt( poz-1 )).mark=='(' &&&& ((Token)tokens.elementAt( poz+1 )).mark==')' || pos==1 &&&& ((Token)tokens.elementAt( 0 )).mark=='(' &&&& ((Token)tokens.elementAt( 2 )).mark==')' ) { tokens.removeElementAt( poz+1 ); tokens.removeElementAt( poz-1 ); } return; }
          步驟 7:在求值的最后一步,向量中剩余的符號(hào)被結(jié)合到字符串,并在屏幕上顯示。

          清單 14. 結(jié)合符號(hào)并顯示結(jié)果


          public static String token_join( Vector tokens ) { String result=new String(); Token t; for ( int i=0; i < tokens.size(); i++ ) { t=(Token)tokens.elementAt( i ); if ( t.mark=='D' ) { double n=((Double)t.token).doubleValue(); result=result + formated_number( n ); } else result=result + t.token; if ( result.endsWith( ".0" ) ) result=result.substring( 0, result.length()-2 ); result=result + " "; } return result; }
          結(jié)論
          本文分析了一個(gè) applet ,它能一步一步的對(duì)算術(shù)表達(dá)式求值。同時(shí)還按順序回顧了最有意思的代碼片段,并論述了兩種不同的表達(dá)式求值方法。

          下一版 W3Eval 有望在各方面得到增強(qiáng),包括有能力添加用戶定義的功能;支持分?jǐn)?shù)、復(fù)數(shù)和矩陣;改良的圖形用戶界面(GUI);大小和速度優(yōu)化以及安全性方面的增強(qiáng)。我鼓勵(lì)您提供您自己對(duì)于增強(qiáng)方面的設(shè)想。

          我希望您會(huì)發(fā)現(xiàn) W3Eval 是個(gè)對(duì)表達(dá)式求值有益的在線工具,它在某種程度上比經(jīng)典的方法更簡單自然。我還期待這里談到的代碼和算法使您明白 Java 語言有助于處理數(shù)學(xué)問題。

          參考資料
          • W3Eval applet 是免費(fèi)的,它的幫助有助于您解決問題。
          • 這張表格展示了 W3Eval 操作符的優(yōu)先級(jí)。
          • 請(qǐng)閱讀波蘭數(shù)學(xué)家 Jan Lukasiewicz 的傳記。
          • Donald Knuth,計(jì)算機(jī)科學(xué)領(lǐng)域卓越的學(xué)者,曾詳盡的就算法的設(shè)計(jì)和分析撰寫和演講。他的主頁提供最近出版的有關(guān)其作品的論文和信息的鏈接。
          • 有興趣隨意編寫 applet 嗎?可以查看我們的教程 Building a Java applet(developerWorks,1999 年)以獲得一步一步的指導(dǎo)。
          • 您會(huì)覺得 Java FAQ 很有用。
          • 還有很多有關(guān) applet 的信息在 Peter Van Der Linden(Prentice Hall PTR/Sun Microsystems 出版社出版,1998 年 12 月)的Just Java 2 中。
          • 由 Ken Arnold、James Gosling 和 David Holmes 撰寫的 The Java Programming Language(Addison Wesley 出版社出版,2000 年 12 月)包含有益的關(guān)于集合的信息。
          • 學(xué)習(xí) Martin Bastiaan 的“A Walk in the Park”(developerWorks,1998 年 1 月),了解更多有關(guān) applet 的知識(shí)。
          • VisualAge for Java 使 applet 的開發(fā)變得輕而易舉。
          • developerWorks Java 技術(shù)專區(qū)查找更多 Java 參考資料。

          關(guān)于作者
          Nikola Stepan 是 ABIT Ltd. 的軟件工程師,他在那里從事銀行業(yè)軟件的設(shè)計(jì)和開發(fā)。他有廣博的信息系統(tǒng)方面的學(xué)術(shù)背景和豐富的編程經(jīng)驗(yàn)(從低級(jí)編程到信息系統(tǒng))。他特別喜歡面向?qū)ο缶幊陶Z言、關(guān)系數(shù)據(jù)庫、因特網(wǎng)編程和系統(tǒng)編程。他于 1999 年在克羅地亞 Varazdin 的 Faculty of Organisation and Informatic 獲得信息系統(tǒng)學(xué)士學(xué)位。他會(huì)說克羅地亞語、英語和一點(diǎn)德語。請(qǐng)通過 nikola.stepan@vz.tel.hr 與 Nikola 聯(lián)系。
          __________________
          “日本固有新奇的武器,我當(dāng)以熱血應(yīng)付;日本固有猛烈的槍炮,我當(dāng)以頭顱拼擋?!?BR>“作為軍人,志在以身報(bào)國,茍有一線之機(jī)不減,自應(yīng)鼓舞勇氣,而為國家盡其最后之犧牲。凡為官為吏,不過一時(shí)職業(yè)之選擇,民族之保存,始為骨頭之歸宿!”

          posted on 2005-12-23 16:28 Ben 閱讀(1343) 評(píng)論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 华宁县| 瑞昌市| 浙江省| 鄂伦春自治旗| 延安市| 盱眙县| 双牌县| 大竹县| 凤庆县| 若尔盖县| 葫芦岛市| 临夏县| 马尔康县| 临沭县| 报价| 镇雄县| 苏尼特左旗| 临夏县| 高安市| 廊坊市| 安陆市| 兴隆县| 东兰县| 扎鲁特旗| 凭祥市| 灵台县| 滦南县| 乌拉特中旗| 酒泉市| 永清县| 东丰县| 江源县| 玉环县| 梅河口市| 洞口县| 翁源县| 安龙县| 灵山县| 老河口市| 万年县| 承德市|