快速精確的對(duì)數(shù)學(xué)表達(dá)式求值(轉(zhuǎn))
步驟:- 表達(dá)式語法分析
- 表達(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 的變量是不限長(zhǎng)度的大寫字母和數(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)組成。
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 類的定義
|
Token
類如清單 2 所示。
清單 2. Token 類
|
檢查正規(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)
|
token 檢查。檢查表達(dá)式語法。確保表達(dá)式所有部分都被認(rèn)為是合法的。
表達(dá)式開頭的檢查(請(qǐng)參閱 清單 4) 。確保表達(dá)式從合法的符號(hào)開始。不可以用操作符、逗號(hào)或閉括號(hào)作為表達(dá)式的開始符。
清單 4. 正確的表達(dá)式開頭的檢查
|
表達(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)的后面。
_ | 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á)式求值:
- 找出嵌入最深的那對(duì)括號(hào)。
- 在這對(duì)括號(hào)中,找出優(yōu)先級(jí)最高的操作符。
- 若這對(duì)括號(hào)中沒有操作符:
- 如果表達(dá)式再不包含任何其它的括號(hào),求值(過程)完成。
- 如果表達(dá)式包含括號(hào),但不包含操作符,則存在一個(gè)函數(shù)。對(duì)函數(shù)求值,然后轉(zhuǎn)到步驟 5。
- 獲取操作數(shù)并執(zhí)行運(yùn)算。
- 從向量中除去用過的符號(hào)并在同一位置放入結(jié)果。
- 除去冗余括號(hào)。
- 將向量中剩余的符號(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)
|
第二步,找出與第一步找到的閉括號(hào)相匹配的開括號(hào),如 清單 6 所示。
清單 6. 找出匹配的開括號(hào)
|
步驟 2:要實(shí)現(xiàn)求值的單步執(zhí)行,W3Eval 在嵌套最深的那對(duì)括號(hào)中找出優(yōu)先級(jí)最高的操作符。(操作符的優(yōu)先級(jí)已硬編碼到 applet 中;請(qǐng)參閱 參考資料以獲取完整的代碼清單。)
清單 7. 找出優(yōu)先級(jí)最高的操作符
|
步驟 3:如果表達(dá)式中不包含其它括號(hào),求值的過程就完成。如果表達(dá)式包含括號(hào),但不包含操作符,則存在需要求值的函數(shù)。
清單 8. 檢查是否還有其它操作符
|
步驟 4:所有的操作符都是二元的,也就是說第一個(gè)操作數(shù)位于操作符之前,第二個(gè)操作符位于操作符之后。
清單 9. 獲取操作數(shù)并執(zhí)行運(yùn)算
|
操作數(shù)可以是變量,還可以是十進(jìn)制、十六進(jìn)制、八進(jìn)制或二進(jìn)制數(shù)。
清單 10. 獲取操作數(shù)
|
接下來的方法將不同計(jì)數(shù)制的數(shù)轉(zhuǎn)化為十進(jìn)制的形式。
清單 11. 將數(shù)轉(zhuǎn)化為十進(jìn)制數(shù)
|
一旦確定操作數(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)
|
步驟 7:在求值的最后一步,向量中剩余的符號(hào)被結(jié)合到字符串,并在屏幕上顯示。
清單 14. 結(jié)合符號(hào)并顯示結(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)典的方法更簡(jiǎn)單自然。我還期待這里談到的代碼和算法使您明白 Java 語言有助于處理數(shù)學(xué)問題。
![]() ![]() |
![]()
|
- 您可以參閱本文在 developerWorks 全球站點(diǎn)上的 英文原文.
- 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 參考資料。
![]() ![]() |
![]()
|
![]() | ||
![]() | 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)系。 |
posted on 2006-10-25 17:31 junky 閱讀(604) 評(píng)論(0) 編輯 收藏 所屬分類: 計(jì)算機(jī)科學(xué),編程思想