| 
第四題 計算機程式 
  
   
使用者設計一個可以自動計算一串數學運算式的計算機,運算式中包括 
由數字、括號及運算符號組成,各別說明如下: 
	- 數字:可能是整數或浮點數,例如;13.456 或 32,且數值不為負。
 
	- 運算符號:"+ , - , * , / , ^",其中    "+,-,*,/" 分別代表算術運算的加 , 減 , 乘 , 除 ,"^" 代表次方運算 ,例如 3^2運算結果會是 9。
 
	- 左、右括號:例如 (24.5+5)*6.3。
 
	- 運算優先權:第一是括號 "()",第二是 "^,*,/",第三是 "+,-"
 
		舉例來說,若輸入 "12+(3.4+5*6.2)/3.2",則結果會顯示 22.75。
 
輸入說明 
  
輸入一串包含 "+,-,*,/,^" 與 "()" 及數字組合的算式,並以 Return 作結束。
  
輸出說明
  
輸出答案為整個運算式的結果,以「四捨五入」取到小數點後第二位, 
如果輸入運算式 不符合一般數學的表示式,則輸出 "N/A"。 
本題無需考慮運算結果發生溢位的問題。
  
範例 
  
    
      | 輸入 | 
      輸出 | 
     
    
      | 12 + (3.4 + 5 * 6.2) / 3.2 | 
      22.75 | 
     
    
      | 5.6 * (6.4 ^ 3 - 8) | 
      1423.21 | 
     
    
      | (1234 + 5678 | 
      N / A | 
     
  
 
 
分析: 
此題是本年度 6 題當中最難一題,應最後做答,時間不足應優先放棄。 
本題是資料結構 堆疊 入門題,使用後序式較容易演算。 
因此本程式解法,必須具備 2 種演算法,分別為: 
1) 中序式轉後序式。 
2) 計算後序式。
  
在解說演算法前,先說明本題與數理相關的不同點。 
	- ) 指數運算,若無括號,則以左結合還是右結合? (可自由設定)
 
	左結合: 3 ^ 2 ^ 4 = ( 3 ^ 2 ) ^ 4 = 9 ^ 4 = 6561 
    右結合: 3 ^ 2 ^ 4 =  3 ^ ( 2  ^ 4 ) = 3 ^ 16 = 43046721 
    很明顯,本題題意是左結合。
	- ) 指數與乘法運算子,誰優先運算,在數學上是以指數優先。
 
	5 * 2 ^ 3 = 5 * ( 2 ^ 3 ) = 5 * 8 = 40 
	但依本題題意,兩者優先度相同,因此變成如下, 
	5 * 2 ^ 3 = ( 5 * 2 ) ^ 3 = 10 ^ 3 = 1000 
	本題以數學角度來看是錯誤的式子,但個人覺得命題者是故意改變運算優先度,其理由是避免解題者,利用語言系統執行 "字串命令運算",如此一來就不用高難度的資料結構堆疊演算了。
 
 
下面是 VB.net 的 "字串命令運算" 
   Dim sc, cmd As Object, d As Double 
   sc = CreateObject("ScriptControl") 
   sc.Language = "VBScript" 
   cmd = sc.Modules.Add("Module1") 
   d = cmd.Eval(str) "這一行指令就可執行運算式了 
   Label1.Text = (CInt(d * CintN) / CintN).ToString() 
   sc = Nothing 
	- 中序式轉後序式演算法
 
	堆疊法:
	
	- 中序轉後序
 
	在中序轉換成後序的過程,我們將以下列的步驟運作: 
	ISP(堆疊內優先權):In Stack Priority 
	ICP(輸入優先權):In Coming Priority 
		
		- 由左至右讀入單一字元。
 
		- 輸入為運算元,則直接輸出。
 
		- "("在堆疊中比任何運算子都小,不過如果在堆疊外,卻比任何運算子優先權都高。
 
		- ISP>=ICP則將堆疊的運算子pop出來,否則就push到堆疊內。
 
		- 若遇")",彈出堆疊內的運算子直到彈出一個"("為止。
 
		 
	其中運算子堆疊的規則是: 
		
		- 碰到左括號"(",一律 push。
 
		- 碰到右括號")",則一直 pop 輸出至後序式,直到遇見左括號,一同抵銷。
 
		- 運算子在堆疊中只能優先序大的壓優先序小的,也就是當運算子在進入堆疊之前和堆疊頂端的運算子比較優先序。如果外面的優先序大,則 push。否則就一直做 pop,直到遇見優先序較小的運算子或堆疊為空。 值得注意的是:左括號在堆疊中優先序最小,亦即,任何運算子都可以壓它。
 
		 
	 
- 計算後序式演算法
 
	
		- 自左而右讀取每一個字。
 
		- 如果是運算元(例如"5),直接 push 進 stack。
 如果是運算子(例如 +),自 stack 中 pop 出兩個運算元進行運算之後將結果 push 進 stack。 
		- 最後 stack 中只剩下一個元素,那就是最後結果。
 
		- 如果發生 stack 已經空了,但是還需要 pop 運算元的情況,表示運算式寫錯了。
 
		- 如果最後 stack 不只剩下一個元素,表示運算式寫錯了。
 
	 
 
請寫一個程式接受使用者輸入 Infix(中置式) 算術運算式字串,算出結果並且印出來。 
此一字串中間沒有空白。 
有 "+" , "-" , "*" , "/" , "^" 五個整數運算子。(含括號) 
每一個整數運算元都是1位數。
  
程式測試
  
承上題,運算元為整數。
  
程式測試
  
 
  
 |