計算機是很多編程初學者都做過的,從最簡單的控制台程式開始,輸入值,輸入運算子,再輸入值,得到一個結果。帶介面的基本上是模仿Windows作業系統的計算機,通過按鈕輸入值和運算子,然後給出運算結果。能不能直接輸入運算式,或者能夠對好幾個運算式進行計算,或者選擇運算式中的一部分進行計算,如果輸入錯誤能不能指出運算式中的錯誤位置?這樣的要求類似於MS SQL的查詢分析器,本系列文章將介紹如何?這樣一個計算機。(這些內容已經涉及到編譯原理,但本人並非電腦專業畢業,只是稍微看了一下編譯原理的資料,專業詞彙比如有限狀態機器之類就不提了,咱也不是很pro,呵呵。)
首先給出一個運算式5*3+12/4,我們拿到這個運算式之後會得到如下分析:
1.乘法的優先順序高後面的加法,先算乘法,乘號兩邊的數分別是5和3,執行乘法5*3=15
2.加法的優先順序沒有後面的除法優先順序高,先算除法,除號兩邊的數是12和4,執行除法12/4=3
3.乘除法做完之後再做加法,這時候加法並不需要知道兩邊到底怎麼計算的,只需要知道兩邊計算後的值就可以了,乘法的值是15,除法的值是3,執行加法15+3=18
在這個運算式後面再加一個步驟:5*3+12/4-8,這時候只不過多了一步操作
4.做完加法後做減法,減號也不需要知道兩邊怎麼計算的,向兩邊請求值,得到加法的值是18,另一邊是一個數字8,不需要計算就直接給它,執行減法18-8=10
再稍微改變一下:5*3+12/4-8/2,計算過程就是
4.做完加法準備做減法,但後面的除法優先順序高,先做除法,除號兩邊的數是8和2,執行除法得到4
5.然後執行減法,減法左邊是執行加法後的值18,右邊是執行除法後的值4,執行減法18-4=14
到此會發現,其實可以把每一個操作符理解成一個數值儲存單元,並且該單元可以根據它兩邊的數值進行一定的計算得到自身的值。它只關心兩邊的值,而不需要關心值是通過什麼演算法得來的。這樣就有了二叉樹的味道,一個結點下面可以有兩個子結點。因此,不管運算式多複雜,最終都只有一個結果,這個結果就是最後一個操作符對它兩邊的值進行計算得到的,而最後一個操作符就可以理解成根節點。下面,就把運算式按照樹的形狀分解:
這裡減法就是根節點,它向下請求值並進行計算。它的下級也是採用同樣的方法向下請求值,請求到值後就執行自身的計算,把計算結果儲存在自己的儲存單元裡,然後讓上一級調用自身的值。最後由根節點計算其下級的值得到整個運算式的值。最終計算完的樹結構如下:
我在實際編程中就是採用這種方法對錶達式進行分析和計算的,
輸入介面(選擇部分運算式計算)
至於如何將運算式分析成樹形結構,以及如何調用下級節點求值,在以後的文章中詳細介紹。
代碼下載:http://files.cnblogs.com/conexpress/ConExpress_MyCalculator.rar
(本程式還有一些細節上的bug,有興趣的朋友可以完善一下。)