1

对不起,如果这是重复的。我想我会稍微改一下我的问题。

我如何使用正则表达式来评估数学表达式?不使用 eval 函数。

示例表达式:

math1 = "1+1"
math2 = "3+2-1"

我希望它适用于表达式中可变数量的数字,就像我在示例中显示的那样。

4

4 回答 4

2

这只是个坏主意。Regexp 不是解析器,也不是评估器。

使用语法来描述你的表达方式。使用像可爱的 ruby​​ gem Treetop这样的正式解析器来解析它。然后评估解析器生成的抽象语法树 (AST)。

天哪,Treetop 的算术示例实际上免费为您提供了解决方案。

于 2013-04-14T06:52:52.703 回答
1

这有点晚了,但我写了一个用于评估任意数学表达式的 gem(它内部不使用 eval):https ://github.com/rubysolo/dentaku

于 2014-02-06T13:49:53.723 回答
0

对于加法和减法,这应该有效

(?:(/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

这仅适用于您提供的示例中的简单加法和减法,因为它依赖于从左到右的关联性。正如其他人所建议的那样,您可能需要正确解析任何更复杂的东西,例如通过构建一个节点树,然后可以以正确的(深度优先?)顺序进行评估。

于 2013-04-14T00:28:59.860 回答
0

这真是乱七八糟……</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

不过,您确实应该考虑使用解析器

于 2013-04-14T00:58:42.020 回答