符号库设计模式

时间:2014-01-14 10:21:50

标签: java design-patterns symbolic-math

我正在构建一个用于符号计算的java库。 我创建了一个抽象表达式类,用于在产品,分数和多项式之间进行各种操作。然而,当我想添加地板和天花板时,事情变得复杂了。我知道周围有这样的库,我想知道是否有特定的设计模式可以遵循,或者是否有任何资源我可以寻求灵感和指导。

1 个答案:

答案 0 :(得分:2)

你最有可能正在解析一个“无上下文的语言”(Type {2,根据Chomsky hierarchy)。试着阅读http://en.wikipedia.org/wiki/LL_parserhttp://en.wikipedia.org/wiki/Pushdown_automaton - 你不一定要理解背后的数学,但它会给你提供线索。

我同意你的看法,复合设计模式对于表达式的对象表示非常有用。以下示例来自我的代码,其目的是保存并打印表达式,但您可以轻松修改它以捕捉到这个想法。

表达式是根对象。它有后代,如CompoundExpression,Number,Variable等。

public interface Expression {
    /**
     * @return a numeric value of the expression
     */
    double getValue();

    /**
     * @return a string representation of the expression
     */
    String getExpression();

    /**
     * @return true if the expression is an atomic expression
     */
    boolean isLeaf();
}

CompoundExpression 是操作的容器,作为其操作数。

public class CompoundExpression implements Expression {

    /**
     * Creates a compound expression.
     * @param operation the specified operation
     * @param operands The specified operands. The amount of operands must exactly
     * match the arity of the operation.
     */
    public CompoundExpression(Operation operation, Expression ... operands) {
        super();
        this.operands = Arrays.asList(operands);
        this.operation = operation;
    }

    /**
     * The expressions which this expression is compound of ;)
     */
    final private List<Expression> operands;

    /**
     * The operation on operands.
     */
    final private Operation operation;

    /**
     * {@inheritDoc}
     */
    @Override
    public String getExpression() {
        return this.operation.compose(this.operands);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public double getValue() {
        return this.operation.calculate(this.operands);
    }

    /** 
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        ....
    }

    /** 
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object obj) {
        ....
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isLeaf() {
        return false;
    }
}

数字是一片叶子。您可以实现更多类型的叶子,例如Variable。

public class Number implements Expression {

    /**
     * Creates an atomic expression with the specified value.
     * @param value the numeric value
     */
    public Number(double value) {
        super();
        this.value = value;
    }

    /**
     * The numeric value of the number.
     */
    private double value;

    /**
     * {@inheritDoc}
     */
    @Override
    public String getExpression() {
        return String.valueOf(this.value);
    }

    /** 
     * {@inheritDoc}
     */
    @Override
    public double getValue() {
        return this.value;
    }

    /** 
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        ....
    }

    /** 
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object obj) {
        ....
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isLeaf() {
        return true;
    }
}

操作保存操作,例如Plus,Sinus,Floor,Ceiling,......如果需要,它还可以实际计算值。< / p>

public interface Operation {

    /**
     * Returns a numeric value of the operation performed on the given operands.
     * 
     * @param operands the list of operands
     * @return a numeric value of the operation
     */
    double calculate(List<Expression> operands);

    /**
     * Returns a string representation of the operation performed on the given operands.
     * @param operands operands the list of operands
     * @return a string representation of the operation
     */
    String compose(List<Expression> operands);

    /**
     * Returns a string representation of the operator
     * @return string representation of the operator
     */
    String getOperator();
}

BinaryOperation 是所有二进制操作的父级。它不一定需要,但它很方便。

public abstract class BinaryOperation implements Operation {

    /**
     * {@inheritDoc}
     */
    @Override
    public String compose(List<Expression> operands) {
        assert (operands.size() == 2);

        final Expression op1 = operands.get(0);
        final Expression op2 = operands.get(1);
        final boolean op1Leaf = op1.isLeaf();
        final boolean op2Leaf = op2.isLeaf();
        final StringBuilder builder = new StringBuilder();
        if (!op1Leaf) {
            builder.append("(");
        }
        builder.append(op1.getExpression());
        if (!op1Leaf) {
            builder.append(")");
        }
        builder.append(this.getOperator());
        if (!op2Leaf) {
            builder.append("(");
        }
        builder.append(op2.getExpression());
        if (!op2Leaf) {
            builder.append(")");
        }
        return builder.toString();
    }
}

二元操作的一个例子:

public class PlusOperation extends BinaryOperation {

    /**
     * {@inheritDoc}
     */
    @Override
    public double calculate(List<Expression> operands) {
        assert (operands.size() == 2);
        return operands.get(0).getValue() + operands.get(1).getValue();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getOperator() {
        return "+";
    }

}    

UnaryOperation 是所有一元操作的父级。它不一定需要,但它很方便。

public abstract class UnaryOperation implements Operation {

    /**
     * {@inheritDoc}
     */
    @Override
    public String compose(List<Expression> operands) {
        assert (operands.size() == 1);
        return this.getOperator() + "(" + operands.get(0).getExpression() + ")";
    }

}

一元操作的一个例子:

public class CosinusOperation extends UnaryOperation {

    /**
     * {@inheritDoc}
     */
    @Override
    public double calculate(List<Expression> operands) {
        assert (operands.size() == 1);
        return Math.cos(operands.get(0).getValue());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getOperator() {
        return "cos";
    }
}

如何使用它。您可以“手动”创建如下表达式:

Expression exp = new CompoundExpression(
    new PlusOperation(),
    new CompoundExpression(
        new DivisionOperation(),
        new CompoundExpression(
            new PlusOperation(), 
            new Number(2), 
            new Number(3)
        ),
        new Number(4)
    ), 
);

您必须使用下推自动机的实现来创建表达式:)