Scala二十四点游戏(3):表达式计算(三)

jerry Scala 2015年11月25日 收藏

在上篇中我们实现了整数的四则运算的算法,这里我们回到之前提到的 5 5 5 1 的例子,我们看看eval ( ? 5 * ( 5 ? 1/5) ? )的结果是多少?

  1. scala> eval ("5*(5-1/5)")
  2. res15: Int = 25

结果为25,我们知道这个结果应该是24,这是因为前面我们的算法都是针对整数的, 1/5 =0 ,当然我们可以把整数改成浮点数,比如,修改eval如下:

  1. def eval(str:String):Double = str match {
  2. ...
  3. case _ => str toDouble
  4. }

重新计算eval (?5*(5-1/5)?)
结果为 24.0,
但是浮点数带来了误差,不是特别理想,我们前面在介绍类和对象时,使用的Rational例子,任何有理数都可以表示成分数,因此可以利用这个Rational来得到表达式计算的精确结果。

  1. class Rational (n:Int, d:Int) {
  2. require(d!=0)
  3. private val g =gcd (n.abs,d.abs)
  4. val numer =n/g
  5. val denom =d/g
  6. override def toString = numer + "/" +denom
  7. def +(that:Rational) =
  8. new Rational(
  9. numer * that.denom + that.numer* denom,
  10. denom * that.denom
  11. )
  12.  
  13. def -(that:Rational) =
  14. new Rational(
  15. numer * that.denom - that.numer* denom,
  16. denom * that.denom
  17. )
  18.  
  19. def * (that:Rational) =
  20. new Rational( numer * that.numer, denom * that.denom)
  21.  
  22. def / (that:Rational) =
  23. new Rational( numer * that.denom, denom * that.numer)
  24.  
  25. def this(n:Int) = this(n,1)
  26. private def gcd(a:Int,b:Int):Int =
  27. if(b==0) a else gcd(b, a % b)
  28. }

利用Rational类,我们修改eval定义如下:

  1. def eval(str:String):Rational = str match {
  2. case Bracket(part1,expr,part2) => eval(part1 + eval(expr) + part2)
  3. case Add(expr1,expr2) => eval(expr1) + eval(expr2)
  4. case Subtract(expr1,expr2) => eval(expr1) - eval(expr2)
  5. case Multiply(expr1,expr2) => eval(expr1) * eval(expr2)
  6. case Divide(expr1,expr2) => eval(expr1) / eval(expr2)
  7. case _ => new Rational (str.trim toInt,1)
  8.  
  9. }

再看看eval (?5*(5-1/5)?)的计算结果:

  1. scala> eval ("5*(5-1/5)")
  2. res16: Rational = 24/1

我们得出来表达式的精确结果,为分数表示,比如:

  1. scala> eval ("4*6")
  2. res17: Rational = 24/1
  3.  
  4. scala> eval ("4*6+3*3+5/7")
  5. res18: Rational = 236/7
  6.  

到目前为止我们有了计算四则运算的算法,下面24的算法就比较简单了,穷举法。

注:Scala中表达式计算的算法还有不少其它方法,比如对表达式的分析可以利用scala.util.parsing.combinator提供的API。