NPI (Neural Program Interpreter) 逆波蘭表達式--什麼是逆波蘭表達式

打算詳細的寫一下NPI, 感覺這個蠻帥的。第一篇就先介紹一下要解決的問題了。

中置表達式與逆波蘭

“先算乘除,再算加減,最先算括號”,這是數學老師告訴我們的用來解決表達式的口訣,可以解決最符合我們人類使用習慣的中置表達式(infix expression):二元運算符會放置在兩個運算數之間。

  • 1+1 用來表達1與1的和,
  • 稍微複雜點的例子比如:(A+B*C+D)*E

我們沒有任何違和的就可以翻譯這則表達式的含義是因爲我們強大的大腦和數學課上的揮汗如雨。😰

不過對於計算機來說,這種中置的表達式就顯得不那麼友好了。計算機首先就要解決表達式裏括號,這裏就涉及至少一層遞歸(計算括號裏的值),而逆波蘭表達式(reverse polish expression / 後置表達式 / postfix expression )裏沒有括號。 讓我繼續用之前的例子來說明一下什麼是逆波蘭表達式。

  • 1 1 + 用來表示1與1的和
  • 之前的(A+B*C+D)*E 變成了 ABC*+D+E*

在逆波蘭表達式中, 所有的運算符只會影響其前面的兩位運算數。從計算機底層結構來看,對於stack machine(寄存器是stack–FILO–先進後出)。ALU會把計算結果寫在棧頂,只需要把表達式從左到右寫進stack registor, 遇到運算符讓就讓ALU算一下,整個流程就很簡單,具有很高的性能。

Shutting-Yard Algorithm

逆波蘭表達式由於這種天然的屬性被廣泛的用到了各種語言中,我們代碼裏的中置表達式會被先轉換成逆波蘭,這裏就會用到我們今天的主角Shutting-Yard Algotithm, 其核心思想是使用stack保存低優先級的操作符,完整的算法描述如下:

/* This implementation does not implement composite functions,functions with variable number of arguments, and unary operators. */

while there are tokens to be read do:
    read a token.
    if the token is a number, then:
        push it to the output queue.
    else if the token is a function then:
        push it onto the operator stack 
    else if the token is an operator then:
        while ((there is a operator at the top of the operator stack)
              and ((the operator at the top of the operator stack has greater precedence)
               or (the operator at the top of the operator stack has equal precedence and the token is left associative))
              and (the operator at the top of the operator stack is not a left parenthesis)):
            pop operators from the operator stack onto the output queue.
        push it onto the operator stack.
    else if the token is a left parenthesis (i.e. "("), then:
        push it onto the operator stack.
    else if the token is a right parenthesis (i.e. ")"), then:
        while the operator at the top of the operator stack is not a left parenthesis:
            pop the operator from the operator stack onto the output queue.
        /* If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. */
        if there is a left parenthesis at the top of the operator stack, then:
            pop the operator from the operator stack and discard it
/* After while loop, if operator stack not null, pop everything to output queue */
if there are no more tokens to read then:
    while there are still operator tokens on the stack:
        /* If the operator token on the top of the stack is a parenthesis, then there are mismatched parentheses. */
        pop the operator from the operator stack onto the output queue.
exit.

source

不過,這個版本太複雜了些, 我們如果只考慮加減乘除以及括號的話,事情會變得容易一點,這裏我就只用pythonlize 的僞代碼寫一下

"""
Input:
    E:中置表達式
    P:優先級map
    S:stack,初始化爲空,用來存運算符
"""
E = *input
P = {
"( outside S":4,
"*/":         3,
"+-":         2,
"( inside S": 1
}
output = []
for all token in E:
	if token not in "+-*/()": 
	    # output.append(token)
	else if token == ")":
	    # Pop S and append to output until after the first '(' in S. 
	    # '('and')' won't append to output"
	else:
	    # Pop S and send to output until P[S.top] lower than P[token]
	    # Push token to S
# Pop whole S

爲了更直觀的理解shutting-yard,這裏提供一個執行過程:

TRACE
Expression:     E/B/H-(B+A/G)..
Stack     :     ...............
-------------------------------
Rev Polish:     E..............
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     /..............
-------------------------------
Rev Polish:     E..............
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     /..............
-------------------------------
Rev Polish:     EB.............
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     /..............
-------------------------------
Rev Polish:     EB/............
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     ...............
-------------------------------
Rev Polish:     EB/............
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     /..............
-------------------------------
Rev Polish:     EB/............
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     /..............
-------------------------------
Rev Polish:     EB/H...........
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     /..............
-------------------------------
Rev Polish:     EB/H/..........
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     ...............
-------------------------------
Rev Polish:     EB/H/..........
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -..............
-------------------------------
Rev Polish:     EB/H/..........
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -(.............
-------------------------------
Rev Polish:     EB/H/..........
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -(.............
-------------------------------
Rev Polish:     EB/H/B.........
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -(+............
-------------------------------
Rev Polish:     EB/H/B.........
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -(+............
-------------------------------
Rev Polish:     EB/H/BA........
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -(+/...........
-------------------------------
Rev Polish:     EB/H/BA........
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -(+/...........
-------------------------------
Rev Polish:     EB/H/BAG.......
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -(+/...........
-------------------------------
Rev Polish:     EB/H/BAG/......
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -(+............
-------------------------------
Rev Polish:     EB/H/BAG/......
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -(+............
-------------------------------
Rev Polish:     EB/H/BAG/+.....
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -(.............
-------------------------------
Rev Polish:     EB/H/BAG/+.....
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -..............
-------------------------------
Rev Polish:     EB/H/BAG/+.....
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     -..............
-------------------------------
Rev Polish:     EB/H/BAG/+-....
###############################
Expression:     E/B/H-(B+A/G)..
Stack     :     ...............
-------------------------------
Rev Polish:     EB/H/BAG/+-....
###############################

source

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章