java實現四則運算應用(基於控制檯)

項目地址:https://gitee.com/wxrqforever/object_oriented_exp1.gitgit

1、需求分析:
  一個基於控制檯的四則運算系統,要能實現生成並計算含有真,假分數,整數的不超過三個運算符帶有括號的四則運算表達式,而且要能根據用戶所提交的答案生成答題報告,答題報告中主要包括,本次答題的正確,錯誤,和重複表達式出現的狀況。生成的表達式和答案要存入文件中。對生成的表達式有以下要求,不能在過程當中產生負數,由於小學生並不會計算負數,以及不能出現除0的狀況,由於小學生不會計算除以0。
  從整個需求來看,大體能夠分爲三個模塊,生成表達式,表達式計算(包括將表達式和答案寫入文件),答題報告的生成(包括表達式的查重和根據輸入完成的校驗)。各個模塊之間關係密切,故採用由下至上的不斷迭代的開發模式,先開發最底層的各個樁模塊,在開發每一個樁模塊時再採用測試驅動開發的方法,從編寫小的測試用例開始開發樁模塊,當對樁模塊進行整合時,再編寫測試模塊,這樣當開發完成後測試也就完成了。
  生成表達式模塊:主要的關鍵點在於如何可以全覆蓋全部不超過三個運算符含有真,假分數,整數的能夠帶有括號的四則運算表達式。在忽略優先級的條件下,咱們觀察表達式形如(1+2+3)*6,1+2+3, 1+2,的三個表達式,咱們會發現任何一個複雜的表達式都可看做,其少一個運算符的表達式和一個運算符以及一個運算數構成,如上的例子中
(1+2+3)*6 能夠看做是由(1+2+3)和*以及6構成,而1+2+3 則能夠看作是由1+2 和+以及3構成。這就給了一個思路只要編寫一個能隨機生成全部狀況下的帶一個運算符的表達式,就能夠經過不斷添加運算符和運算操做數的方式而窮盡全部的可能。
  表達式計算:可採用將隨機生成的表達式轉換爲後綴,在對後綴表達式進行計算完成。
  答題報告的生成:關鍵點在於如何實現查重,首先咱們要明白何爲重複的表達式?根據題目中的定義「程序一次運行生成的題目不能重複,即任何兩道題目不能經過有限次交換+和×左右的算術表達式變換爲同一道題目。例如,23 + 45 = 和45 + 23 = 是重複的題目,6 × 8 = 和8 × 6 = 也是重複的題目。3+(2+1)和1+2+3這兩個題目是重複的,因爲+是左優先計算的,1+2+3等價於(1+2)+3,也就是3+(1+2),也就是3+(2+1)。可是1+2+3和3+2+1是不重複的兩道題,由於1+2+3等價於(1+2)+3,而3+2+1等價於(3+2)+1,它們之間不能經過有限次交換變成同一個題目。" 仔細觀察題目中所給的兩個例子,你會發現這裏所說的重複的意思就是你不能破壞本來計算時的優先級,在這個基礎上你能夠交換加法或者乘法的。解析一下題中的例子,好比3+(2+1)和1+2+3這兩個題目,爲何是重複的呢?按照優先級,咱們是如何計算左邊題目的,是先計算2+1的這個加法再計算3加上2+1的結果的這個加法的對吧,而右邊這個題目根據加法的左結合,先計算1+2 的這個加法 再計算3加上1+2 這個結果的加法,運算時的符號的優先級並無被改變僅僅改變了加法的左右操做數,知足重複的定義,因此是重複的。
  再看一個不重複的例子,1+2+3和3+2+1,一樣的左邊的題目,先計算的是1+2的這個加法再計算3加上1+2的結果的這個加法,而右邊的則是先計算3+2的這個加法再計算1加上3+2的結果的加法.能夠理解爲在進行運算時整個運算的流程是不一樣的,因此是不一樣的表達式.
經過上述的分析咱們能夠看到如何斷定兩個表達式是否重複關鍵在於若是在計算這兩個表達式時的流程徹底一致或者僅在加法或者乘法運算時交換了左右操做數則這樣的兩個運算表達式是重複的,這樣的分析很容易讓咱們相到用後綴表達式解決查重,但僅僅依靠後綴表達式是不夠的,後綴表達式是可以體現計算過程但卻沒法用於判斷兩個表達式之間計算過程是否相同的直接體現,這是·兩個重複的表達式極可能會有不一樣後綴表達式。好比以(1+2)*3+5和3*(1+2) +5 爲例,(1+2)*3+5的後綴表達式爲1 2 + 3 * 5 + 而3*(1+2) +5的後綴表達式爲3 1 2 + * 5+,雖然是相同運算過程的體現但表達式之間的差距卻很是的大,那該如何解決?
  所謂相同的運算過程就是,你在作什麼運算我也作什麼運算,你的操做數是啥個人操做數也是啥,出於這個引入一個新的表達式,我將其命名爲查重表達式,他的結構是運算在前後面跟着這個運算符的操做數,以上述爲例(1+2)*3+5的查重表達式就爲: +12 * 3 +5 這個表達式的含義就是第一個運算的是加法,加法的操做數是2 和3 第二個運算是乘法,乘法的操做數是前一步計算的結果和3以此類推,而3*(1+2) +5的查重表達式爲:+12 * 3+5 與上述徹底一致!這樣在作查重是隻需判斷查重表達式是否一致或者在查重表達式中第一個字符爲‘+’ 或者‘*’的狀況下後續的兩個操做數互換位置後是否一致便可。也就是說上述的查重表達式於+21 * 3+5 也是等價的。
那該如何生成查重表達式,所謂的查重表達式就是描述表達式正在運算的過程,那就在你使用後綴表達式計算時,去生成便可。算法以後給出
2、功能設計:
功能設計如圖:
算法

 


com.wx.appEntrance是做爲項目的入口。
com.wx.test 是做爲測試功能使用
com.wx.randomTool是做爲生成隨機的四則運算表達式的,共有四個類組成其中RandExpressionExport(可直接生成表達式)是頂層類,是對RandOperatorNumberExport(可隨機生成各種操做數和操做符)進一步封裝,而RandOperatorNumberExport是對RandomExportMachine(可生成數字和字符)的進一步封裝,Ruler則是描述生成表達式的功能.
com.wx.expression是描述表達式的結構
com.wx.calculateTool是用於計算表達式,PostfixExpression用於生成後綴表達式,CalculateRuler描述計算規則,CalculateExpression頂層類對可直接計算表達式,對前面兩個類的封裝。
com.wx.fileIO用於實現文件操做
com.wx.expressionCnki 用於實現表達式的查重,工具類.
com.wx.report 用於生成答題報告.express

3、代碼實現數據結構

3.1表達式類主要用於存儲表達式的代碼,以下:app

 

 

3.2.1 用於隨機產生一個表達式的頂層類RandExpressionExport中的產生隨機表達式getExpression方法代碼以下:dom

 

3.2.2 用於隨機產生一個表達式的頂層類RandExpressionExport中的隨即產生一個操做符表達式的getOneOperatorExpression方法的代碼以下:工具

(其他多操做符的狀況均是對該方法的進一步封裝)測試

 

 3.2.3用於隨機產生一個表達式的頂層類RandExpressionExport中的隨即產生帶有兩個操做符的表達式的getTwoOperatorExpression方法的代碼以下:spa

 

3.3.1用於將表達式轉換成後綴表達式的PostfixExpression類中的getPostFixExpression代碼以下:設計

 

3.3.2用於計算後綴表達式的CalculateExpression類中的calculatePostFixExpression方法代碼以下:

3.3.3用於描述計算規則的CalculateRuler中的用於化簡表達式的方法simplificationFracrion的代碼以下:

 

 4.1用於實現查重的Cnki類中的獲得查重表達式的getCnkiExpressionArray方法的代碼以下:

 

 4.2用於實現查重的Cnki類中的判斷兩個表達式是否重複的代碼以下:

4.3用於生成報告的AnswerResport中生成答題報告getAnswerResport方法的代碼:
4.4用於生成報告的AnswerResport中生成查重報告cnkiExpressionAnswerReport方法的代碼:

 4、測試運行:

 測試截圖以下:

輸入題目數爲10 生成的數字範圍爲10

文件中的截圖以下:

對於查重進行單獨測試:
當輸入的表達式爲1+2+3 與3+(2+1)時,截圖以下:其中第一,二行爲1+2+3的後綴表達式和查重表達式,第三,四行爲3+(2+1)的後綴表達式和查重表達式。

第五行爲查重結果,餘下的爲查重報告。

當輸入的表達式爲1+2+3 與3+1+2時,截圖以下:其中第一,二行爲1+2+3的後綴表達式和查重表達式,第三,四行爲3+1+2的後綴表達式和查重表達式。

第五行爲查重結果,餘下的爲查重報告。

當輸入的表達式爲(1+2)*3+5  與3*(1+2) +5 時,截圖以下:其中第一,二行爲(1+2)*3+5的後綴表達式和查重表達式,第三,四行爲3*(1+2) +5 的後綴表達式和查重表達式。

第五行爲查重結果,餘下的爲查重報告

 5、psd我的過程:

6、小結.

  1.其實我的認爲查重的沒什麼實際應用的必要,不管查重用什麼實現,不論是用二叉樹仍是本文所採用的後綴轉換查重表達式,時間複雜度均在n平方左右,更不用說用於存儲二叉樹或者查重表達式的所消耗的存儲空間裏,而且,假設是生成10個表達式,且運算操做數的範圍爲10,生成兩個重複的表達式的機率在接近千分之一,幾乎是不可能的。

  2.測試驅動開發的模式很好用。

  3.在需求分析和設計上應該投入更多的時間,前期設計時並無考慮查重應用致使後期若想採用二叉樹代價略高,只能採用查重表達式的方式,其實如今想一想比較好的處理方法應該是採用二叉樹的數據結構方式去生成表達式,去計算表達式,去查重表達式,若只在查重階段採用二叉樹,則代價過高。

相關文章
相關標籤/搜索