QT簡易計算器 表示式計算核心演算法(二)

2021-08-06 02:51:45 字數 3475 閱讀 4447

概述:上篇我主要介紹了用qt做計算器的整個流程,這次主要就是分析一下,計算器表示式計算的演算法部分。因為也找了很多別人寫的**,但大多都是只支援個位數的加減乘除,小數也不支援,所以就在原有框架上,修改,優化,讓其滿足我想要的功能。

1,表示式計算思路。

表示式資料操作符分割–>轉為逆波蘭表示式–>計算逆波蘭表示式值–>輸出結果。

2,表示式計算詳解。

(1)表示式資料操作符分割

首先我們得到了乙個字串表示式,我們將資料和操作符分割。

如:表示式—————> 「23+1.23-(2-5)*3」

分割後為「23」 「+」 「1.23」 「- 」「( 」「2」「 -」 「5」 「)」「*」 「3」,然後將其存入乙個qstring陣列,這樣資料,操作符分割就便於後面計算,辨別是資料還是操作符了。遍歷陣列,只要第乙個字元不是0-9就是操作符了。

下面是這部分**詳解:

/*將表示式的資料,操作符分割,依次存入mask_buffer陣列中*/

int calculator::mask_data(qstring expression, qstring *mask_buffer)

mask_buffer[k] = temp;

}else

}return k;

}

(2)轉為逆波蘭表示式。

既然用到逆波蘭表示式,首先了解一下什麼是逆波蘭表示式。我們正常的表示式是中綴表示式,逆波蘭就是將中綴表示式轉化為字尾表示式。我們就簡單粗暴一些,例子。

1+2*3-(2+5)———>中綴表示式。

1,2,3,*,+,2,5,+,- ———>字尾表示式。

中綴到字尾如何轉化呢,下面就是詳細的規則了:

首先我們定義乙個陣列a,堆疊b。陣列a用於儲存最後的字尾表示式,堆疊b就是乙個過渡器,幫助我們轉化,再定義操作符的優先順序,如+ - * / ( )。

從左到右遍歷整個表示式。

1,遇到數字加入陣列a。

2,遇到左括號直接入棧到b。

3,遇到右括號,堆疊b出棧,加入到陣列a中,直到遇到左括號,將左括號出棧但不加入陣列a中。

4,如果遇到的是運算子:

(1)當堆疊b為空,直接入棧到b。

(2)當堆疊不為空,當前運算子優先順序大於堆頂運算子優先順序,入棧到b。

(3)當堆疊不為空,當前運算子優先順序小於等於堆頂運算子優先順序,b出棧到a陣列中,直到堆頂運算子優先順序小於當前運算子優先順序,再將當前運算子入棧b。

5,當遍歷完整個表示式,堆疊b不為空,依次出棧加入到a陣列中。

下面詳細步驟轉化過程:

陣列a[100],堆疊b.

表示式:1+2*3-(2+5)

遍歷:"1" ------> a b

"+" ------> a b

"2" ------> a b

"*" ------> a b //"*"優先順序高於"+"

"3" ------> a b

"-" ------> a b //"-"優先順序不大於"*",不大於"+",*,+出棧到a

"(" ------> a b

"2" ------> a b

"+" ------> a b

"5" ------> a b

")" ------> a b //遇到右括號,+出棧到a中

a b //遍歷結束,b中不為空,"-"出棧到a中

下面是這部分原始碼:

/*獲取操作符優先順序*/

int calculator::priority(qstring data)

/*將獲取到的分割好的表示式陣列,轉化為逆波蘭表示式,存入陣列repolish中*/

int calculator::re_polish(qstring *mask_buffer,qstring *repolish,int length)

else

if(mask_buffer[j] == ")")

if(st2.top() == "(")

st2.pop();

}else

if(st2.empty() || priority(mask_buffer[j]) > priority(st2.top()))

st2.push(mask_buffer[j]);

else

st2.push(mask_buffer[j]);}}

while(!st2.empty())

return i;

}

(3)計算逆波蘭表示式值。

計算就比較簡單了,我們只需要維護乙個儲存資料的堆疊就行了,我們有乙個逆波蘭表示式陣列,上面得到的,再新建乙個堆疊st。遍歷整個逆波蘭表示式陣列,遇到數字直接壓棧到st中,遇到「+」,「-」,「*」,「/」,就取出st棧頂元素a,st.pop(),取下乙個棧頂元素b,st.pop()。計算數值對應操作符值(如操作符為+,b+a),將計算的值入棧到st中。直到表示式遍歷完,堆疊裡只剩乙個資料,就是最後的結果值,取出。

我們還是以 1,2,3,*,+,2,5,+,- 為例。

遍歷陣列a = 

"1"------> st

"2"------> st

"3"------> st

"*"------> st //2*3 = 6

"+"------> st //1+6 = 7

"2"------> st

"5"------> st

"+"------> st //2+5 = 7

"-"------> st //7-7 = 0 即最後結果為0

下面是這部分原始碼:

/*計算逆波蘭表示式值並顯示*/

double calculator::repolish_calculat(qstring *repolish,int length)

else

else if(repolish[m] == "-")

else if(repolish[m] == "*")

else if(repolish[m] == "/")}}

}qstring res = qstring::number(st

.top(),'g',10);

ui->display->clear();

ui->put_data->settext(res);

return st

.top();

}

表示式計算器

早在上大學的時候,就想編寫乙個可以計算數學表示式的計算器,因為windowsxp自帶的計算器不支援表示式輸入,當要計算乙個算式時,不太方便。表示式計算器看似簡單,但要想把它做完善,不太容易,經過幾次改進之後,於一年前完成了這個小程式,雖然可能會有一些不足,不過也不打算再投入時間了,價值不大,只是拿來...

Qt之簡易計算器

寫之原因 本人是一名菜鳥,學了qt也就十天左右吧。學習一種對我來說比較新的語言,最好的學習方式就是去真刀真槍的幹一場!所以,閒來無事,就打算寫乙個小應用。思來想去,覺得還是寫乙個簡單的計算器吧,因為其他的涉及的還不是特別深,感覺自己能駕馭的就是計算器這種,簡單而實用的小應用。1 calculate....

QT實現簡易計算器

定義a用來儲存lineedit顯示內容 定義b用來儲存運算子等 ifndef widget h define widget h include qt begin namespace namespace ui qt end namespace class widget public qwidget e...