2009-10-09 49 views
10

什麼是實現一個Python程序的最佳方式,它將接收一個字符串並根據運算符優先級輸出結果(例如:「4 + 3 * 5」將輸出19)。我一直在尋找解決這個問題的方法,但他們都太複雜了,我正在尋找一個(相對)簡單的問題。我希望能夠添加其他運算符(例如最大運算符 - 4 $ 2 = 4),或者我也更關注這個學術上的問題,而不是專業意義上的問題 - 我想知道如何這樣做。數學表達式評估

+1

http://docs.python.org/reference/simple_stmts.html#exec – nlucaroni

+1

看看:http:// stackoverflow。com/questions/400050 /閱讀並運行一個數學表達式在python –

+1

嘗試「評估」,而不是「解決」,這表明能夠找到「x」給出「4x - 6 = 4」。 – dmckee

回答

16

如果您「學術上有興趣」,您想了解如何編寫具有運算符優先級的解析器。

Simple Top-Down Parsing in Python是一個不錯的文章,它構建了一個示例解析器來完成您想要做的事情:評估數學表達式。

我強烈建議你去編寫自己的第一個解析器 - 這是其中的一個「啊,這是如何工作的」瞬間!

+0

我看了一眼,看起來你鏈接的文章實現了Python中的Interpreter模式。 –

1

我對Python和任何極端的Pythonic方法都不太熟悉,但是您可以看看在四人幫中定義的Interpreter pattern。它是爲處理「語言」而設計的,數學表達式遵循特定的語言和規則。事實上,Wikipedia上的例子實際上是一個RPN計算器的Java實現。

+18

那麼他們現在正在調用解析一個「模式」呢?這一定是計算機科學中使用最多的詞...... – Noldorin

+0

這不僅僅是解析。它以一種乾淨,可理解的方式在給定的「語言」中解析「句子」。 –

+1

@Thomas:真的,這不是比通用解析更具體。我的意思是,所有的解析都涉及某種「句子」;任何像樣的解析器都是乾淨的/可以理解的,至少在某種形式下是如此。 (以遞歸下降爲例) 另外,s/their /它們是:P – Noldorin

1

這就是「eval」函數在Python中的作用。

result = eval(expression) 

要小心的是它可以做很多更多,主要是調用函數,所以爲了安全起見,你應該確保它無法訪問當地人或全局。此外,您還可以訪問內置的方法,其中包括棘手的進口所以你需要阻止訪問,以及:

result = eval(expression, {'__builtins__': None}, {}) 

但是如果你需要的安全性,只是,那就是如果你允許任何人輸入任何表達。

當然,因爲你用這種方式阻止了所有locla變量的使用,所以你不需要使用任何變量,因此你只需要傳入應該在字典中訪問的那些變量。

vars = {'__builtins__': None, 'x': x} 
result = eval(expression, vars, {}) 

或類似的。

+1

eval的問題出現在表達式=「system.os(rm -rf \)」時。如果你在* nix中以root身份運行它,那麼繁榮就是機器。或者如果它與Windows相同,尤其是因爲有太多人以管理員身份運行Windows。 –

+2

只有你已經完成'從os導入系統'並且不提供globals和locals目錄。這是我在我的例子中爲此做的。 –

+0

在表達式中,你可以再次從os導入系統然後使用它。所以是的,我的例子只有在你已經從系統導入os時才能工作,但是通過擴展我的表達式,你可以導入任何你想要的東西並使用它。 –

2

另一種可能性是查看Pyparsing,這是一個通用的解析器構建器。它比你需要的更強大,但實施起來可能會更快。

+0

pyparsing wiki(pyparsing.wikispaces.com)包含幾個算術表達式解析器的例子 - fourFn.py和simpleArith.py。即使你不使用pyparsing,fourFn.py也可能對這種解析器如何實現運算符優先級有啓發作用。 – PaulMcG

+0

我剛剛意識到OP想要添加其他操作符。 simpleArith.py顯示瞭如何添加階乘(!)運算符 - evalArith.py(位於頁面底部)擴展了simpleArith.py,並顯示瞭如何評估已分析的值。 – PaulMcG