class Quotient implements Expression {
private final Expression numerator;
private final Expression denominator;
public Quotient(Expression numerator, Expression denominator) {
this.numerator = numerator;
this.denominator = denominator;
}
public Expression getNumerator() {
return numerator;
}
public Expression getDenominator() {
return denominator;
}
@Override
public Expression takeDerivative() {
return new Quotient(
new Difference(
new Product(numerator.takeDerivative(), denominator),
new Product(numerator, denominator.takeDerivative()),
),
new Product(denominator, denominator)
);
}
@Override
public Expression simplify() {
Expression n = numerator.simplify();
Expression d = denominator.simplify();
if (n.equals(Constant.ZERO) || d.equals(Constant.ONE)) {
return n;
}
if (n.equals(d)) {
return Constant.ONE;
}
if (d instanceof Quotient) {
if (n instanceof Quotient) {
return new Quotient(
new Product(n.getNumerator(), d.getDenominator()),
new Product(d.getNumerator(), n.getDenominator())
).simplify();
} else {
return new Quotient(
new Product(n, d.getDenominator()),
d.getNumerator()
).simplify();
}
} else if (n instanceof Quotient) {
return new Quotient(
n.getNumerator(),
new Product(d, n.getDenominator())
).simplify();
}
return new Quotient(n, d);
}
@Override
public Operator getOperator() {
return DIVISION;
}
@Override
public boolean equals(Object object) {
if (! object instanceof Expression) {
return false;
}
if (object == this) {
return true;
}
Expression t = simplify();
Expression o = ((Expression) object).simplify();
if (! t instanceof Quotient) {
return t.equals(o);
}
if (! o instanceof Quotient) {
return false;
}
Quotient qt = (Quotient) t;
Quotient qo = (Quotient) o;
return qt.getNumerator().equals(qo.getNumerator())
&& qt.getDenominator().equals(qo.getDenominator());
}
}
If you make separate classes for each operation, you don't need the switch
anymore. Each class provides its own method instead. This can work for both takeDerivative
and for simplify
.
I did not implement hashCode
, but it might be advisable to do so. Otherwise, funky things could happen if you used this as a key in a HashMap
, put it in a HashSet
, or otherwise did something that relied on hashCode
.
I may be missing simplification cases. For example, \$\frac{x^2 + x}{x}\$ would not simplify to \$x+1 \forall x \ne 0\$ with this method. These are the ones that came to mind with easy implementations.