在上篇中我们实现了整数的四则运算的算法,这里我们回到之前提到的 5 5 5 1 的例子,我们看看eval ( ? 5 * ( 5 ? 1/5) ? )的结果是多少?
scala> eval ("5*(5-1/5)") res15: Int = 25
结果为25,我们知道这个结果应该是24,这是因为前面我们的算法都是针对整数的, 1/5 =0 ,当然我们可以把整数改成浮点数,比如,修改eval如下:
def eval(str:String):Double = str match { ... case _ => str toDouble }
重新计算eval (?5*(5-1/5)?)
结果为 24.0,
但是浮点数带来了误差,不是特别理想,我们前面在介绍类和对象时,使用的Rational例子,任何有理数都可以表示成分数,因此可以利用这个Rational来得到表达式计算的精确结果。
class Rational (n:Int, d:Int) { require(d!=0) private val g =gcd (n.abs,d.abs) val numer =n/g val denom =d/g override def toString = numer + "/" +denom def +(that:Rational) = new Rational( numer * that.denom + that.numer* denom, denom * that.denom ) def -(that:Rational) = new Rational( numer * that.denom - that.numer* denom, denom * that.denom ) def * (that:Rational) = new Rational( numer * that.numer, denom * that.denom) def / (that:Rational) = new Rational( numer * that.denom, denom * that.numer) def this(n:Int) = this(n,1) private def gcd(a:Int,b:Int):Int = if(b==0) a else gcd(b, a % b) }
利用Rational类,我们修改eval定义如下:
def eval(str:String):Rational = str match { case Bracket(part1,expr,part2) => eval(part1 + eval(expr) + part2) case Add(expr1,expr2) => eval(expr1) + eval(expr2) case Subtract(expr1,expr2) => eval(expr1) - eval(expr2) case Multiply(expr1,expr2) => eval(expr1) * eval(expr2) case Divide(expr1,expr2) => eval(expr1) / eval(expr2) case _ => new Rational (str.trim toInt,1) }
再看看eval (?5*(5-1/5)?)的计算结果:
scala> eval ("5*(5-1/5)") res16: Rational = 24/1
我们得出来表达式的精确结果,为分数表示,比如:
scala> eval ("4*6") res17: Rational = 24/1 scala> eval ("4*6+3*3+5/7") res18: Rational = 236/7
到目前为止我们有了计算四则运算的算法,下面24的算法就比较简单了,穷举法。
注:Scala中表达式计算的算法还有不少其它方法,比如对表达式的分析可以利用scala.util.parsing.combinator提供的API。