第四次作业-四则运算
前言
? 作業要求地址:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/997
? 結對伙伴:宋雨http://www.cnblogs.com/songyuu/
? git:https://git.coding.net/Vrocker/f4.git
?
?
?
要求一
? 具體要求:參考《構建之法》第4章兩人合作,結對編程上述功能,要求每人發布隨筆1篇 (代碼是共同完成的,博客是分別完成的)。 (1) 給出每個功能的重點、難點、編程收獲。(2)給出結對編程的體會,以及 (3) 至少5項在編碼、爭論、復審等活動中花費時間較長,給你較大收獲的事件。
?
一、每個功能的重點、難點
1.功能一
實現這個功能的重點是在于隨機生成參與運算的數字和四個運算符。在Python中,random模塊可以用于生成隨機數。這樣很方便的使用了這一模塊下的部分函數,來實現這一功能。
部分代碼如下:
def _f4(self):from random import randint as rfrom random import uniform as rufrom fractions import Fraction as fops = ['+', '-', '*', '/']bra = ['(', '', ')']_l1 = r(0, 1)_l2 = r(0, 1)_l3 = r(0, 1)_r1 = r(1, 2)_r2 = r(1, 2)_r3 = r(1, 2)
2.功能二
這個功能中加入了括號的運算。括號參與運算是最大的難點。
本科期間學習的數據結構這門課程中,在講到棧與隊列的時候,逆波蘭即后綴表達式是棧在表達式求知中的應用。這個應用是棧比較常見的,而且十分常用。所以看到這個要求加上題目中老師的提醒,我就開始翻找數據結構書來尋找相應的方法。同時用??梢院芎玫慕鉀Q括號匹配,這樣一來兩者結合可以通過棧來完成需求。經過查閱數據結構書加上自己的思考嘗試解決這一難題。
括號匹配算法總結如下:
1、初始化一個空棧,開始順序讀入括號。
2、如果是右括號,則或者是置于棧頂的最急迫期待得以消解,或者是不合法的情況(括號序列不匹配,退出程序)。
3、若是左括號,則作為一個新的更急迫的期待壓入棧中,自然使原有的在棧中的所有未消解的期待的急迫性降了一級。算法結束,棧為空,否則括號序列不匹配。
根據這一算法,可以解決括號匹配的問題。
同時表達式求值的實現是棧應用的一個典型的例子。中綴表達式不僅依賴運算符的優先級,同時還要處理括號。后綴表達式的運算符在操作數后面。在后綴表達式中已考慮了運算符的優先級,沒有括號,只有操作數和運算符。并且中綴表達式和后綴表達式可以相互轉換。通過后綴表達式計算相應式子的值,其過程為:
1、順序掃描表達式的每一項
2、如果是操作數,則將其壓入棧中
3、如果是操作符<op>,則連續從棧中推出兩個操作數,x和y,形成運算的指令x<op>y
4、將計算的結果重新壓入棧中。
5、當表達式所有的項豆掃描并且處理完畢后,棧頂存放的就是最后的計算結果。
根據書中的介紹,??梢院芎玫慕鉀Q這一需求。在最開始分配任務的時候,我一開始想用c++來編寫程序,因為自己相對于其他語言比較熟悉c++,所以在考慮這一個問題的時候我當時也是想要采用c++來實現。自己根據書中的范例代碼并且查閱了網上相關代碼,嘗試進行改寫,來滿足題目需求。
首先讀取隨機生成的表達式,然后用上次作業用到的vector,構造vector<string>儲存成普通的中綴表達式然后遍歷vector<string>再用剛剛提到的算法利用棧來構造后綴表達式。最后遍歷構造好的vector<string>中存放在后綴表達式對彈出棧的兩個操作數進行運算,將結果壓入棧中。則最后剩余在棧中的一項就是計算的最終結果。c++的部分代碼如下:
1 for (auto &oper : vec) { 2 if (oper == "+" || oper == "-") { 3 while (true) { 4 if (sta.empty() || sta.top() == "(") 5 break; 6 p_vec.push_back(sta.top()); 7 sta.pop(); 8 } 9 sta.push(oper); 10 } 11 else if (oper == "*" || oper == "/") { 12 while (true) { 13 if (sta.empty() || sta.top() == "+" || 14 sta.top() == "-" || sta.top() == "(") 15 break; 16 p_vec.push_back(sta.top()); 17 sta.pop(); 18 } 19 sta.push(oper); 20 } 21 else if (oper == ")") { 22 while (true) { 23 if (sta.top() == "(") { 24 sta.pop(); 25 break; 26 } 27 p_vec.push_back(sta.top()); 28 sta.pop(); 29 } 30 } 31 else sta.push(oper); 32 } 33 while (!sta.empty()) { 34 p_vec.push_back(sta.top()); 35 sta.pop(); 36 } c++
?
?
?
?
不僅僅是計算,括號的生成順序也是這個要求的難點。也可以定義棧用逆波蘭的方法來解決。
?
?
因為我和我的結對伙伴都想用python來完成這次作業,所以如果要用棧那么c++的代碼就要改寫成python的。一開始在看題目要求的時候,觀察到操作數是固定的四個數字,就采用直接固定四個操作數,沒有采用棧而是直接判斷括號的優先級,來生成括號并且計算。在之后的python編寫中因為我自己對python學習還是太少,編寫不出python的逆波蘭方法。在嘗試多次后,甚至想把作業重新用c++編寫,但是換編程語言的工作量太大,所以就用比較原始的方法完成這個需求。
在此之后還會不斷嘗試用python實現逆波蘭。
?
3.功能三
這個功能的主要難點是在于命令行參數的實現。
在上次作業中,c++語言的命令行參數花費了我很多時間才會完全使用。python中可以用argparse標準庫解決。它是解析命令行參數和選項的標準模塊。在學習argparse模塊的使用方法后,實現了python?的命令行參數功能??傮w感覺比c++要簡便不少。
部分代碼如下:
1 import argparse 2 parser = argparse.ArgumentParser() 3 parser.add_argument("-c", "--cin") 4 args = parser.parse_args() 5 if args.cin == None: 6 f4()._f4_input() 7 else: 8 f4()._f4_integer_parser(args.cin)?
4.功能四
這個功能中,最重要的就是支持分數。這個功能宋雨同學花費了很長時間解決了這個難點很多的功能。經過他的講解介紹,用fractions標準庫可以實現這一功能。采用python內置函數eval()。但eval()函數的輸出為浮點數,故采用這一函數生成的分數分子分母位數都很多。測試之后發現不滿足題目的要求,所以在宋雨同學的解決意見下限制輸出的位數。經過實驗,發現可以實現。所以采用了這一方法。
部分代碼如下:
1 def _f4_answer(self,eq): 2 from fractions import Fraction as f 3 _answer = f(eval(eq)).limit_denominator(1000) 4 _answer = str(_answer) 5 return(_answer)?
?
二、體會
在開始編寫程序的時候,決定選擇了python進行編寫。因為我對python掌握很不好,所以本次主要的代碼都是由宋雨同學完成,給我了很多幫助,我也在結對編程的過程中不斷學習python。
因為我自己的原因,相比較python,c++我掌握的相對好一些,所以在遇到難題的時候想把代碼換成c++。但是因為工作量太大,而且我認識到不能回避難題,所以接著用python進行編寫。這次結對編程我體會到相互合作的重要性,結對伙伴不僅能給自己幫助也能共同進步一起努力。
?
三、花費時間較長,給你較大收獲的事件
1、一開始沒有采用面向對象來編寫代碼,在討論之后將代碼改成oop方式。
2、棧的問題花費的時間很多,對python?掌握還是太差。
3、分數功能的實現,包括查資料測試都花費了很多時間。
4、進行單元測試的時候框架換了很多。
5、一起編寫的時候,宋雨同學對我講解了很多python的知識。讓我對python的學習有了信心。
?
?
?
?
要求二
?
地點:寢室
電腦:msi、win10
軟件:pycharm
語言:python
?
照片:
?
?
測試截圖
1
?
2
?
3
?
?
轉載于:https://www.cnblogs.com/vrocker/p/7650258.html
總結
以上是生活随笔為你收集整理的第四次作业-四则运算的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ldap数据库--ODSEE--复制协议
- 下一篇: Notepad++中的高级查找