Python實現簡單表示式求值

2021-10-09 04:50:00 字數 3997 閱讀 4842

問題**於清華大學出版社2023年第二版《資料結構》,3.2節 表示式求值。書中採用了「算符優先法」並提供了演算法的偽**,本文是偽碼的python實現。

問題的簡要描述(具體可參考《資料結構》)

本文僅討論個位數的包含加減乘除小括號的表示式,並規定表示式以『#』結束。

表示式例項:3*(7-2)#

不討論表示式語法錯誤的情況

θ₁\θ₂+-

*/()

#+>

>

<

<

<

>

>

->

>

<

<

<

>

>

*>

>

>

>

<

>

>

\>

>

>

>

<

>

>

(<

<

<

<

<

=)>

>

>

>

>

>

#<

<

<

<

<

=由於表示式以『#』結束,為了演算法簡潔,在表示式的最左邊虛設乙個『#』,構成一對。

為實現算符優先演算法,可以使用兩個工作棧。optr寄存運算子,opnd寄存運算元和運算結果。

演算法的基本思想為:

1.置運算元棧為空棧,表示式起始符『#』為運算子棧的棧底元素;

2.依次讀入表示式中的字元,若是運算元則進opnd棧;若是運算子,則和optr棧的棧頂運算子比較優先權後,進行相應操作,直至表示式求值完畢。

演算法的偽**表示

funcexp_reduced:operandtype;

inistack(optr);

push(optr,』#』);

instack(opnd);

read(w);

whilenot((w=』#』)and(gettop(optr)=』#』))do

ifwnotinopthenpush(opnd,w)

elsecaseprecede(gettop(optr),w)of

『<』:[push(optr,w); read(w)];

『=』:[x:=pop(optr); read(w)];

'『>』:[theta:=pop(optr); b=pop(opnd); a:=pop(opnd); push(opnd,operate(a,theta,b))]

endc;

return(gettop(opnd))

endf;

python實現

import numpy

defis_int

(x):

try:

int(x)

return

true

except valueerror:

return

false

#自定義函式,用於判斷字元是否為數字

defcalculate

(expression)

: change =

#將符號轉換為數字,用於對應二維陣列

prior = numpy.array([[

1,1,

-1,-

1,-1

,1,1

],[1

,1,-

1,-1

,-1,

1,1]

,[1,

1,1,

1,-1

,1,1

],[1

,1,1

,1,-

1,1,

1],[

-1,-

1,-1

,-1,

-1,0

,2],

[1,1

,1,1

,2,1

,1],

[-1,

-1,-

1,-1

,-1,

2,0]

])#用二維陣列表示符號間的優先關係,即上文中的**。

#其中1為》;0為=;-1為<;2用於佔位,也可以用於判斷表示式錯誤。在**中沒有討論表示式錯誤的情況。

operator =

['#'

] number =

#operator為偽碼中的optr棧,即運算子棧;number為opnd棧,即運算元棧。

i =0#通過下標遍歷字串

while

not(expression[i]

=='#'

and operator[-1

]=='#')

:if is_int(expression[i]):

) i +=

1elif prior[change[operator[-1

]]][change[expression[i]]]

==-1:

) i +=

1elif prior[change[operator[-1

]]][change[expression[i]]]

==0: operator.pop(

) i +=

1elif prior[change[operator[-1

]]][change[expression[i]]]

==1: op = operator.pop(

) b = number.pop(

) a = number.pop(

)str

(eval

(a + op + b)))

#計算a和b通過op運算子後的結果。我直接使用了eval函式,如果不用,可以寫四個判斷進行計算。

#需要注意的是eval接收的引數為字串,要將計算得到的結果轉化為字元再壓入棧內

return

int(number[-1

])#number內存放的是字元,需要轉化為數字

while

true

: string =

input

("input:"

)if string ==

"quit"

:break

else

:print

(calculate(string)

)#測試

個人想法

我在看到算符優先關係的**的時候挺迷惑的,帶入乙個例子模擬計算步驟就比較好理解了。

對於演算法的基礎實現,感覺python**量少的優勢完全沒有體現出來,c++也是差不多這樣寫的。不過如果直接用eval的話,python一行就可以出結果了。

參考資料

《資料結構》第二版 嚴蔚敏 吳偉民 編著 清華大學出版社 2023年6月 p45-47

簡單表示式求值

char evaluateexpression else c getchar gettop optr,e else gettop opnd,e return e 核心演算法如圖所示,基本思想是利用棧的基本性質和操作 數棧和算符棧兩棧分開 結合算符優先順序順序的二維陣列定義,完成基本算數表示式的核心演...

字尾表示式實現表示式求值

看到別人寫的乙個表示式求值程式,想到很久之前寫的乙個。中間有個字串轉數值型,可以用stringstream來實現或者c語言裡面的strtod直接得到 include include include include includeusing namespace std class data doubl...

簡單表示式求值(只有 )

題目如下 輸入僅有一行,為需要你計算的表示式,表示式中只包含數字 加法運算子 和乘法運算子 且沒有括號,所有參與運算的數字均為 0 到 2 31 1 之間的整數。輸入資料保證這一行只有 0 9 這 12 種字元。輸出格式 輸出只有一行,包含乙個整數,表示這個表示式的值。注意 當答案長度多於 4 位時...