第四次作业-四则运算
前言
? 作業(yè)要求地址:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/997
? 結(jié)對(duì)伙伴:宋雨http://www.cnblogs.com/songyuu/
? git:https://git.coding.net/Vrocker/f4.git
?
?
?
要求一
? 具體要求:參考《構(gòu)建之法》第4章兩人合作,結(jié)對(duì)編程上述功能,要求每人發(fā)布隨筆1篇 (代碼是共同完成的,博客是分別完成的)。 (1) 給出每個(gè)功能的重點(diǎn)、難點(diǎn)、編程收獲。(2)給出結(jié)對(duì)編程的體會(huì),以及 (3) 至少5項(xiàng)在編碼、爭(zhēng)論、復(fù)審等活動(dòng)中花費(fèi)時(shí)間較長(zhǎng),給你較大收獲的事件。
?
一、每個(gè)功能的重點(diǎn)、難點(diǎn)
1.功能一
實(shí)現(xiàn)這個(gè)功能的重點(diǎn)是在于隨機(jī)生成參與運(yùn)算的數(shù)字和四個(gè)運(yùn)算符。在Python中,random模塊可以用于生成隨機(jī)數(shù)。這樣很方便的使用了這一模塊下的部分函數(shù),來(lái)實(shí)現(xiàn)這一功能。
部分代碼如下:
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.功能二
這個(gè)功能中加入了括號(hào)的運(yùn)算。括號(hào)參與運(yùn)算是最大的難點(diǎn)。
本科期間學(xué)習(xí)的數(shù)據(jù)結(jié)構(gòu)這門課程中,在講到棧與隊(duì)列的時(shí)候,逆波蘭即后綴表達(dá)式是棧在表達(dá)式求知中的應(yīng)用。這個(gè)應(yīng)用是棧比較常見(jiàn)的,而且十分常用。所以看到這個(gè)要求加上題目中老師的提醒,我就開始翻找數(shù)據(jù)結(jié)構(gòu)書來(lái)尋找相應(yīng)的方法。同時(shí)用棧可以很好的解決括號(hào)匹配,這樣一來(lái)兩者結(jié)合可以通過(guò)棧來(lái)完成需求。經(jīng)過(guò)查閱數(shù)據(jù)結(jié)構(gòu)書加上自己的思考嘗試解決這一難題。
括號(hào)匹配算法總結(jié)如下:
1、初始化一個(gè)空棧,開始順序讀入括號(hào)。
2、如果是右括號(hào),則或者是置于棧頂?shù)淖罴逼绕诖靡韵?#xff0c;或者是不合法的情況(括號(hào)序列不匹配,退出程序)。
3、若是左括號(hào),則作為一個(gè)新的更急迫的期待壓入棧中,自然使原有的在棧中的所有未消解的期待的急迫性降了一級(jí)。算法結(jié)束,棧為空,否則括號(hào)序列不匹配。
根據(jù)這一算法,可以解決括號(hào)匹配的問(wèn)題。
同時(shí)表達(dá)式求值的實(shí)現(xiàn)是棧應(yīng)用的一個(gè)典型的例子。中綴表達(dá)式不僅依賴運(yùn)算符的優(yōu)先級(jí),同時(shí)還要處理括號(hào)。后綴表達(dá)式的運(yùn)算符在操作數(shù)后面。在后綴表達(dá)式中已考慮了運(yùn)算符的優(yōu)先級(jí),沒(méi)有括號(hào),只有操作數(shù)和運(yùn)算符。并且中綴表達(dá)式和后綴表達(dá)式可以相互轉(zhuǎn)換。通過(guò)后綴表達(dá)式計(jì)算相應(yīng)式子的值,其過(guò)程為:
1、順序掃描表達(dá)式的每一項(xiàng)
2、如果是操作數(shù),則將其壓入棧中
3、如果是操作符<op>,則連續(xù)從棧中推出兩個(gè)操作數(shù),x和y,形成運(yùn)算的指令x<op>y
4、將計(jì)算的結(jié)果重新壓入棧中。
5、當(dāng)表達(dá)式所有的項(xiàng)豆掃描并且處理完畢后,棧頂存放的就是最后的計(jì)算結(jié)果。
根據(jù)書中的介紹,棧可以很好的解決這一需求。在最開始分配任務(wù)的時(shí)候,我一開始想用c++來(lái)編寫程序,因?yàn)樽约合鄬?duì)于其他語(yǔ)言比較熟悉c++,所以在考慮這一個(gè)問(wèn)題的時(shí)候我當(dāng)時(shí)也是想要采用c++來(lái)實(shí)現(xiàn)。自己根據(jù)書中的范例代碼并且查閱了網(wǎng)上相關(guān)代碼,嘗試進(jìn)行改寫,來(lái)滿足題目需求。
首先讀取隨機(jī)生成的表達(dá)式,然后用上次作業(yè)用到的vector,構(gòu)造vector<string>儲(chǔ)存成普通的中綴表達(dá)式然后遍歷vector<string>再用剛剛提到的算法利用棧來(lái)構(gòu)造后綴表達(dá)式。最后遍歷構(gòu)造好的vector<string>中存放在后綴表達(dá)式對(duì)彈出棧的兩個(gè)操作數(shù)進(jìn)行運(yùn)算,將結(jié)果壓入棧中。則最后剩余在棧中的一項(xiàng)就是計(jì)算的最終結(jié)果。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++
?
?
?
?
不僅僅是計(jì)算,括號(hào)的生成順序也是這個(gè)要求的難點(diǎn)。也可以定義棧用逆波蘭的方法來(lái)解決。
?
?
因?yàn)槲液臀业慕Y(jié)對(duì)伙伴都想用python來(lái)完成這次作業(yè),所以如果要用棧那么c++的代碼就要改寫成python的。一開始在看題目要求的時(shí)候,觀察到操作數(shù)是固定的四個(gè)數(shù)字,就采用直接固定四個(gè)操作數(shù),沒(méi)有采用棧而是直接判斷括號(hào)的優(yōu)先級(jí),來(lái)生成括號(hào)并且計(jì)算。在之后的python編寫中因?yàn)槲易约簩?duì)python學(xué)習(xí)還是太少,編寫不出python的逆波蘭方法。在嘗試多次后,甚至想把作業(yè)重新用c++編寫,但是換編程語(yǔ)言的工作量太大,所以就用比較原始的方法完成這個(gè)需求。
在此之后還會(huì)不斷嘗試用python實(shí)現(xiàn)逆波蘭。
?
3.功能三
這個(gè)功能的主要難點(diǎn)是在于命令行參數(shù)的實(shí)現(xiàn)。
在上次作業(yè)中,c++語(yǔ)言的命令行參數(shù)花費(fèi)了我很多時(shí)間才會(huì)完全使用。python中可以用argparse標(biāo)準(zhǔn)庫(kù)解決。它是解析命令行參數(shù)和選項(xiàng)的標(biāo)準(zhǔn)模塊。在學(xué)習(xí)argparse模塊的使用方法后,實(shí)現(xiàn)了python?的命令行參數(shù)功能。總體感覺(jué)比c++要簡(jiǎn)便不少。
部分代碼如下:
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.功能四
這個(gè)功能中,最重要的就是支持分?jǐn)?shù)。這個(gè)功能宋雨同學(xué)花費(fèi)了很長(zhǎng)時(shí)間解決了這個(gè)難點(diǎn)很多的功能。經(jīng)過(guò)他的講解介紹,用fractions標(biāo)準(zhǔn)庫(kù)可以實(shí)現(xiàn)這一功能。采用python內(nèi)置函數(shù)eval()。但eval()函數(shù)的輸出為浮點(diǎn)數(shù),故采用這一函數(shù)生成的分?jǐn)?shù)分子分母位數(shù)都很多。測(cè)試之后發(fā)現(xiàn)不滿足題目的要求,所以在宋雨同學(xué)的解決意見(jiàn)下限制輸出的位數(shù)。經(jīng)過(guò)實(shí)驗(yàn),發(fā)現(xiàn)可以實(shí)現(xiàn)。所以采用了這一方法。
部分代碼如下:
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)?
?
二、體會(huì)
在開始編寫程序的時(shí)候,決定選擇了python進(jìn)行編寫。因?yàn)槲覍?duì)python掌握很不好,所以本次主要的代碼都是由宋雨同學(xué)完成,給我了很多幫助,我也在結(jié)對(duì)編程的過(guò)程中不斷學(xué)習(xí)python。
因?yàn)槲易约旱脑?#xff0c;相比較python,c++我掌握的相對(duì)好一些,所以在遇到難題的時(shí)候想把代碼換成c++。但是因?yàn)楣ぷ髁刻?#xff0c;而且我認(rèn)識(shí)到不能回避難題,所以接著用python進(jìn)行編寫。這次結(jié)對(duì)編程我體會(huì)到相互合作的重要性,結(jié)對(duì)伙伴不僅能給自己幫助也能共同進(jìn)步一起努力。
?
三、花費(fèi)時(shí)間較長(zhǎng),給你較大收獲的事件
1、一開始沒(méi)有采用面向?qū)ο髞?lái)編寫代碼,在討論之后將代碼改成oop方式。
2、棧的問(wèn)題花費(fèi)的時(shí)間很多,對(duì)python?掌握還是太差。
3、分?jǐn)?shù)功能的實(shí)現(xiàn),包括查資料測(cè)試都花費(fèi)了很多時(shí)間。
4、進(jìn)行單元測(cè)試的時(shí)候框架換了很多。
5、一起編寫的時(shí)候,宋雨同學(xué)對(duì)我講解了很多python的知識(shí)。讓我對(duì)python的學(xué)習(xí)有了信心。
?
?
?
?
要求二
?
地點(diǎn):寢室
電腦:msi、win10
軟件:pycharm
語(yǔ)言:python
?
照片:
?
?
測(cè)試截圖
1
?
2
?
3
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/vrocker/p/7650258.html
總結(jié)
以上是生活随笔為你收集整理的第四次作业-四则运算的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ldap数据库--ODSEE--复制协议
- 下一篇: Notepad++中的高级查找