对不起,如果这是重复的。我想我会稍微改一下我的问题。
我如何使用正则表达式来评估数学表达式?不使用 eval 函数。
示例表达式:
math1 = "1+1"
math2 = "3+2-1"
我希望它适用于表达式中可变数量的数字,就像我在示例中显示的那样。
这有点晚了,但我写了一个用于评估任意数学表达式的 gem(它内部不使用 eval):https ://github.com/rubysolo/dentaku
对于加法和减法,这应该有效
(?:(/d+)([-+]))+(/d+)
这表示:
请注意,每个单独的数字和符号都在组 1..n 中捕获
因此,要评估,您可以使用捕获 1 和 3,应用捕获 2 中的符号。然后将捕获 4 中的符号(如果存在)与之前的结果和捕获 5 中的数字(如果捕获 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
这仅适用于您提供的示例中的简单加法和减法,因为它依赖于从左到右的关联性。正如其他人所建议的那样,您可能需要正确解析任何更复杂的东西,例如通过构建一个节点树,然后可以以正确的(深度优先?)顺序进行评估。
这真是乱七八糟……</p>
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
不过,您确实应该考虑使用解析器。