编写Java类以评估算术表达式

时间:2013-01-25 00:54:12

标签: java

我必须用Java编写一个类,它支持用2个方法表示算术表达式 - eval和toString,使用以下黑盒:

Expression e = 
new Multiplication( 
    new Addition( 
        new Double(2.5), 
        new Double(3.5)), 
    new UnaryMinus( 
        new Integer(5))); 
System.out.println(e.eval());   // should print out -30.0 
System.out.println(e.toString());   // should print out ((2.5 + 3.5) * (-(5))) 

我该如何设计这样的课程?哪些工具?哪种设计模式?

5 个答案:

答案 0 :(得分:2)

您只需要适当地实现每个运营商的toStringeval。然后,在应用自己的部分之前,根据需要在每个组件上调用toStringeval

因此Addition.eval()将执行return left.eval() + right.eval();

同样,Addition.toString()将执行return "(" + left.toString() + " + " + right.toString() + ")";

为了实现这一目标,您将使用Rob建议的Composite模式的接口来构建覆盖这些方法的适当类。

答案 1 :(得分:2)

  

我如何设计这样的课程?

在你给出的黑匣子示例代码中有很多线索。

  • 您需要一个名为interface的{​​{1}}(或可能abstract class},其Expression方法。 eval方法需要返回某种数字类型 - eval是一个不错的选择,但还有其他选项。

  • 您需要一些表达式类(实现或扩展表达式),例如DoubleMultiplicationAddition。这些需要提供UnaryMinus方法的实现。他们还需要覆盖默认的eval方法来打印表达式。

  • 表达式类还需要具有隐含的参数类型的构造函数

需要一点思考才能弄清楚如何处理这两个问题

toString()

new Multiplication( 
    new Addition( 
        new Double(2.5), 
        new Double(3.5)), 
    new UnaryMinus( 
        new Integer(5))); 

......但是你可以解决这个问题。并通过自己解决来学习。 (或者可能不会打扰,因为严格来说,实施你向我们展示过的例子并不重要。)

  

哪些工具?

没有必要......除了Java JDK安装(显然)。使用您最喜欢/推荐的Java IDE,或简单的文本编辑器和JDK命令行工具。

  

哪种设计模式?

无要求。只是一点点"普通或花园品种"多态性。常规OO类和接口。

答案 2 :(得分:2)

希望这有帮助

setp 1:

public abstract class Expression
{
    public abstract decimal Evaluate();
    public abstract string toString();
}

第2步:

public abstract class ValueNode:Expression
{
    public int intvalue;
    public decimal decvalue;
    public abstract decimal TEvaluate();
    public abstract string TtoString();

    public override decimal Evaluate()
    {
        return TEvaluate();
    }

    public override string toString()
    {
        return TtoString();
    }
}

步骤2.1:

public abstract class OperationNode:Expression
{
   public Expression left;
   public Expression right;
   public override decimal Evaluate()
    {
        return this.EEvaluate();
    }
    public override string toString()
    {
        return this.EtoString();
    }
    public abstract decimal EEvaluate();
    public abstract string EtoString();

}

第3步:

public class UnaryMinus:OperationNode
{
    public UnaryMinus(Expression Left)
     {
        this.left = Left;

    }
    public override decimal EEvaluate()
    {
        return -(this.left.Evaluate());
    }

    public override string EtoString()
    {
        return string.Format("(-({0}))",left.toString()); ;
    }

}

第4步:

public class DecimalClass:ValueNode
{
    public DecimalClass(decimal decimalValue)
    {
        this.decvalue = decimalValue;
    }

    public override decimal TEvaluate()
    {
        return this.decvalue;
    }

    public override string TtoString()
    {
        return this.decvalue.ToString();
    }
}

第5步:

public class Integer : ValueNode
{
    public Integer(int decimalValue)

    {
        this.intvalue = decimalValue;
    }

 public override decimal TEvaluate()

    {
        return this.intvalue;
    }

    public override string TtoString()

    {
        return this.intvalue.ToString();
    }
}

第6步:

public  class Addition:OperationNode
 {

   public Addition(Expression Left, Expression Right)

    {
        this.left = Left;
        this.right = Right;
    }
    public override decimal EEvaluate()
    {
        return left.Evaluate()+ right.Evaluate();
    }
    public override string EtoString()
    {
        return string.Format("({0}+{1})",left.toString(),right.toString()); ;
    }
}

第7步:

public class Multiplication : OperationNode

{
    public Multiplication(Expression Left, Expression Right)
    {
        this.left = Left;
        this.right = Right;
    }
    public override decimal EEvaluate()
    {
        return left.Evaluate()* right.Evaluate();
    }

    public override string EtoString()
    {
        return string.Format("({0}*{1})",left.toString(),right.toString()); ;
    }
}

第8步:

public class Substraction:OperationNode
{
   public Substraction(Expression Left, Expression Right)
    {
        this.left = Left;
        this.right = Right;
    }
    public override decimal EEvaluate()
    {
        return left.Evaluate()- right.Evaluate();
    }

    public override string EtoString()
    {
        return string.Format("({0}-{1})",left.toString(),right.toString()); ;
    }
}

第9步:

public  class Division: OperationNode
{
   public Division(Expression Left, Expression Right)
    {
        this.left = Left;
        this.right = Right;
    }
    public override decimal EEvaluate()
    {
        return left.Evaluate()/ right.Evaluate();
    }

    public override string EtoString()
    {
        return string.Format("({0}/{1})",left.toString(),right.toString()); ;
    }
}

第10步:

class Program
{
    static void Main(string[] args)
    {

        callComposit();
        Console.ReadKey();
    }

    private static void callComposit()
    {
        //Expression ((2.5+3.5)*(-(5)))
        Multiplication multiplication = new Multiplication(new Addition(new DecimalClass(2.5m), new DecimalClass(3.5m)), new UnaryMinus(new Integer(5)));
        Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication.toString(), multiplication.Evaluate()));



        //Expression (5/6)
        Division division = new Division(new Integer(5), new Integer(6));
        Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", division.toString(), division.Evaluate()));
        //Expression ((2.5-3.5)*(-(5)))
        Multiplication multiplication2 = new Multiplication(new Substraction(new DecimalClass(2.5m), new DecimalClass(3.5m)), new UnaryMinus(new Integer(5)));
        Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication2.toString(), multiplication2.Evaluate()));
        //Expression ((2.5/3.5)*(-(5)))
        Multiplication multiplication3 = new Multiplication(new Division(new DecimalClass(2.5m), new DecimalClass(3.5m)), new UnaryMinus(new Integer(5)));
        Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication3.toString(), multiplication3.Evaluate()));

        //Expression ((2.5/3.5)*(-(5))* 3.5)
        Multiplication multiplication4 = new Multiplication(new Multiplication(new Division(new DecimalClass(2.5m), new DecimalClass(3.5m)), new UnaryMinus(new Integer(5))), new DecimalClass(3.5m));
        Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication4.toString(), multiplication4.Evaluate()));


        //Expression ( 3.5*(2.5/3.5)*(-(5)))
        Multiplication multiplication5 = new Multiplication(new Multiplication(new DecimalClass(3.5m), new Division(new DecimalClass(2.5m), new DecimalClass(3.5m))), new UnaryMinus(new Integer(5)));
        Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication5.toString(), multiplication5.Evaluate()));

        //Expression ( 3.5*(2.5/3.5)+ 3.5 *(-(5)))
        Multiplication multiplication6 = new Multiplication(new Addition(new Multiplication(new DecimalClass(3.5m), new Division(new DecimalClass(2.5m), new DecimalClass(3.5m))), new DecimalClass(3.5m)), new UnaryMinus(new Integer(5)));
        Console.WriteLine(string.Format("\r\n Expression {0} resulted in {1}", multiplication6.toString(), multiplication6.Evaluate()));
    }
}

请评论是否需要做任何事情来做得比这更好 快乐的编码

答案 3 :(得分:1)

您需要Expression课程,然后是CompoundExpressionTerminalExpression。听起来像什么样的模式? Composite。然后,如果您愿意,可以使用访问者进行解析。

当你提供一种语言时,无论是算术还是其他一些解释的命令,都会有复合命令,例如:表达式4 +(5 * 2)将被解析为多个命令并添加到CompoundExpression中,当您调用eval时,它将遍历其表达式树来计算答案。 (设计模式对你有好处,顺便说一下,学习它们会让你成为一个更好的编码器。)

答案 4 :(得分:1)

如果允许修改黑盒子的使用,那么构建器模式可能是一个很好的方法。它看起来更像是:

Builder builder = new MathBuilder(); 表达式e = builder.add(new Double(2.5))。add(new Double(3.5).multiply(-5);

你必须围绕操作顺序计算细节,但总的来说,它似乎很好地利用了模式。快速搜索会出现很多例子。