Scala - 代数运算的字符串

时间:2015-05-13 10:39:26

标签: string scala

我有一个代表一些基本代数运算的字符串,例如:

 "42 * 67 + 4"

我想要一个类型为

的函数
 function (operation: String) : Int = {}

这样它需要一串代数运算并返回实际的最终值,在这种情况下:2818

我知道如何从这样的字符串中提取数字,但我不清楚如何提取数学运算,如'+',' - ','*','/'并实际计算它们。< / p>

2 个答案:

答案 0 :(得分:2)

在没有任何外部库的情况下,实现Shunting-yard algorithm进行此类计算相当简单:

def calculate(operation: String): Int = {
  var results: List[Int] = Nil
  var operators: List[String] = Nil

  def precedence(operator: String) = operator match {
    case "+" | "-" => 0
    case "*" | "/" => 1
  }

  def execute(operator: String): Unit = {
    (results, operator) match {
      case (x :: y :: rest, "+") => results = (y + x) :: rest
      case (x :: y :: rest, "-") => results = (y - x) :: rest
      case (x :: y :: rest, "*") => results = (y * x) :: rest
      case (x :: y :: rest, "/") => results = (y / x) :: rest
      case (_, _) => throw new RuntimeException("Not enough arguments")
    }
  }

  for (term <- "[1-9][0-9]*|[-+/*]".r.findAllIn(operation)) {
    util.Try(term.toInt) match {
      case util.Success(number) => results ::= number
      case _ =>
        val (operatorsToExecute, rest) = 
          operators.span(op => precedence(op) >= precedence(term))
        operatorsToExecute foreach execute
        operators = term :: rest
    }
  }
  operators foreach execute

  results match {
    case res :: Nil => res
    case _ => throw new RuntimeException("Too many arguments")
  }
}

这使用整数除法:

scala> calculate("3 / 2")
res0: Int = 1

并且具有正确的加法和乘法优先级:

scala> calculate("2 + 2 * 2")
res1: Int = 6

支持:

  • 更多种类的操作,
  • 括号,例如2 * (2 + 2)
  • 浮点计算,
  • 更好地测试公式内容(目前它只是忽略除数字和运算符之外的所有字符)
  • 不会抛出错误(例如,返回Try[Int]Option[Int]等,而不是返回裸Int或抛出错误的当前行为)

留给读者练习。

对于更复杂的事情,当然最好使用其他答案中提出的scala-parser-combinators或某些第三方解析库。

答案 1 :(得分:0)

所以,@GáborBakos发表了他的开玩笑评论,而我还在编写和测试我的开玩笑答案,但无论如何我都会发布。

注意:它有效。有时。一点点。 注2:这是个玩笑!

def function(operation: String) = {
  val js = new javax.script.ScriptEngineManager().getEngineByName("JavaScript")
  js.eval(operation) match { case i: Integer => i.asInstanceOf[Int] }
}

function("42 * 67 + 4")
// => 2818 : Int