對不起,如果這是重複的。我想我會稍微改正我的問題。Ruby用正則表達式評估表達式,沒有eval
如何使用正則表達式來評估數學表達式?不使用eval函數。
實施例的表達式:
math1 = "1+1"
math2 = "3+2-1"
我想它和用於數字表達式中的可變數量的工作像我在實施例表明。
對不起,如果這是重複的。我想我會稍微改正我的問題。Ruby用正則表達式評估表達式,沒有eval
如何使用正則表達式來評估數學表達式?不使用eval函數。
實施例的表達式:
math1 = "1+1"
math2 = "3+2-1"
我想它和用於數字表達式中的可變數量的工作像我在實施例表明。
對於加和減,這應該工作
(?:(/d+)([-+]))+(/d+)
這意味着:
注意,每個單獨的數字和符號組中被捕獲1..1
所以評估,你可以採取捕獲1和3,從捕獲2.將符號然後從捕獲應用標誌4(如果存在的話),與之前的結果,並從捕獲5(如果Capture 4存在必須存在)的數量等等...
這樣評價,在僞代碼:
i=1
result=capture(i)
loop while i <= (n-2) (where n is the capture count):
If capture(i+1) == "-" // is subtraction
result = result - capture(i+2)
Else // is addition
result = result + capture(i+2)
End if
i = i + 2
End while
這只是要w ork用於簡單的加法和減法,就像您提供的示例一樣,因爲它依賴於從左到右的關聯性。正如其他人所建議的那樣,您可能需要正確解析更復雜的任何東西,例如,構建一個節點樹,然後可以按正確的(深度優先?)順序進行評估。
這是真的很亂......
math2 = "12+3-4"
head, *tail = math2.scan(/(?<digits>\d+)(?<op>[\+\-\*\/])?/)
.map{|(digits,op)|
[digits.to_i,op]
}
.reverse
tail.inject(head.first){|sum,(digits,op)|
op.nil? ?
digits :
digits.send(op,sum)
}
# => 11
你真的應該考慮parser雖然。
這只是一個壞主意。正則表達式不是解析器,也不是評估者。
使用語法來描述您的表達式。用像可愛的紅寶石寶石Treetop這樣的正式解析器解析它。然後評估解析器產生的抽象語法樹(AST)。
天哪,Treetop的arithmetic example實際上給你免費的解決方案。
+1「這只是一個壞主意」。 +1「正則表達式不是解析器,也不是評估者」。 -1「使用語法來描述你的表達式」 - 由OP_are_ regular給出的例子,因此RegEx可以正確地描述這個(簡單的)語法,一個正式的解析器可能被視爲過度殺傷。 -1「Treetop的算術例子實際上免費爲您提供解決方案。」 - 看着這個語法,有證明是過度的。 1 + 1-1-1 = 0 :-) – Sepster
啊來吧,@Sepster。當有人想要「解析表達式」時,有99%的時間他們最終意味着各種各樣的算術運算符,其優先級和括號不同 - 這是不規則的。它總是以眼淚結束,直到他們學會解析。這是已有50多年曆史的技術,我們需要停止抽出錯誤的工具。 – dbenhur
同意。但是這個問題並沒有提到任何關於「解析表達式」的問題,相反,它的標題是「用_regex_評估一個表達式」,並且在它的正文中「我怎麼用_regex_來評估一個數學表達式?」。這並不是說我認爲它應該這樣做。只是它可以完成。順便說一句,因爲我以前從未見過Treetop。 – Sepster
這是一個有點晚,但我寫了一個寶石用於評估任意數學表達式(它不EVAL內部使用):https://github.com/rubysolo/dentaku
的[紅寶石evalute不EVAL?](HTTP
可能重複:// stackoverflow.com/questions/15994101/ruby-evalute-without-eval) – Hauleth
所以只是數字和加/減?你爲什麼不寫一個解析器呢? – Blender
@ŁukaszNiemier是的,我知道,它的一個稍微不同的問題..感謝檢查我雖然兄弟 – Tommy