很抱歉,如果这是重复的话。我以为我会稍微改回一下我的问题。
我如何使用正则表达式来评估数学表达式?不使用eval函数。
示例表达式:
math1 = "1+1"
math2 = "3+2-1"
我希望它能在表达式中使用可变数量的数字,就像我在示例中所示。
答案 0 :(得分:2)
这只是一个坏主意。 Regexp不是解析器,也不是评估器。
使用语法来描述你的表达。使用正式的解析器解析它,比如可爱的ruby gem Treetop。然后评估解析器生成的抽象语法树(AST)。
Gosh,Treetop的arithmetic example实际上为您提供免费的解决方案。
答案 1 :(得分:1)
这有点晚了,但是我写了一个用于评估任意数学表达式的宝石(并且它没有在内部使用eval):https://github.com/rubysolo/dentaku
答案 2 :(得分:0)
对于加法和减法,这应该有效
(?:(/d+)([-+]))+(/d+)
这意味着:
请注意,每个单独的数字和符号都会在组1..n
中捕获因此,为了评估,您可以捕获捕获1和3,应用捕获2中的符号。然后应用捕获4中的符号(如果存在)与先前结果和捕获5中的数字(如果捕获必须存在) 4存在)等......
所以要在psuedo代码中进行评估:
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
这仅适用于您提供的示例中的简单加法和减法,因为它依赖于从左到右的关联性。正如其他人所建议的那样,你可能需要正确地解析任何更复杂的东西,例如通过构建一个节点树,然后可以以正确的(深度优先?)顺序进行评估。
答案 3 :(得分:0)
这真是一团糟......
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。