Expression implements Parcelable { @NonNull BigDecimal evaluate(boolean priority, int scale, RoundingMode roundingMode) { if (numbers.size() != operators.size() + 1) { throw new IllegalStateException("Numbers and operators aren't balanced."); } if (numbers.size() == 1) return numbers.get(0); List<BigDecimal> nbs = new ArrayList<>(numbers); List<Operator> ops = new ArrayList<>(operators); if (priority) { int i = 0; while (i < ops.size()) { Operator op = ops.get(i); if (op == Operator.MULTIPLY) { ops.remove(i); BigDecimal n1 = nbs.get(i); BigDecimal n2 = nbs.remove(i + 1); nbs.set(i, n1.multiply(n2)); } else if (op == Operator.DIVIDE) { ops.remove(i); BigDecimal n1 = nbs.get(i); BigDecimal n2 = nbs.remove(i + 1); nbs.set(i, n1.divide(n2, scale, roundingMode)); } else { i++; } } } while (!ops.isEmpty()) { Operator op = ops.remove(0); BigDecimal n1 = nbs.get(0); BigDecimal n2 = nbs.remove(1); if (op == Operator.ADD) { nbs.set(0, n1.add(n2)); } else if (op == Operator.SUBTRACT) { nbs.set(0, n1.subtract(n2)); } else if (op == Operator.MULTIPLY) { nbs.set(0, n1.multiply(n2)); } else { nbs.set(0, n1.divide(n2, scale, roundingMode)); } } return nbs.remove(0).stripTrailingZeros(); } Expression(); private  Expression(Parcel in); @NonNull @Override String toString(); @Override void writeToParcel(@NonNull Parcel out, int flags); @Override int describeContents(); static final Creator<Expression> CREATOR; }
@Test public void twoSum() { Expression expr = new Expression(); expr.numbers.add(new BigDecimal("12.1")); expr.operators.add(Expression.Operator.ADD); expr.numbers.add(new BigDecimal("-24.8")); BigDecimal result = expr.evaluate(false, 8, RoundingMode.HALF_UP); assertEquals(result, new BigDecimal("-12.7")); }
@Test public void sumAndMultiply() { Expression expr = new Expression(); expr.numbers.add(new BigDecimal("3")); expr.operators.add(Expression.Operator.ADD); expr.numbers.add(new BigDecimal("4")); expr.operators.add(Expression.Operator.MULTIPLY); expr.numbers.add(new BigDecimal("5")); BigDecimal result1 = expr.evaluate(false, 8, RoundingMode.HALF_UP); assertEquals(result1, new BigDecimal("35")); BigDecimal result2 = expr.evaluate(true, 8, RoundingMode.HALF_UP); assertEquals(result2, new BigDecimal("23")); }
@Test public void longExpression() { Expression expr = new Expression(); expr.numbers.add(new BigDecimal("-1")); expr.operators.add(Expression.Operator.DIVIDE); expr.numbers.add(new BigDecimal("6")); expr.operators.add(Expression.Operator.ADD); expr.numbers.add(new BigDecimal("5")); expr.operators.add(Expression.Operator.MULTIPLY); expr.numbers.add(new BigDecimal("12")); expr.operators.add(Expression.Operator.DIVIDE); expr.numbers.add(new BigDecimal("3")); expr.operators.add(Expression.Operator.DIVIDE); expr.numbers.add(new BigDecimal("8")); expr.operators.add(Expression.Operator.SUBTRACT); expr.numbers.add(new BigDecimal("-10")); BigDecimal result1 = expr.evaluate(false, 8, RoundingMode.HALF_UP); assertEquals(result1, new BigDecimal("12.41666667")); BigDecimal result2 = expr.evaluate(true, 8, RoundingMode.HALF_UP); assertEquals(result2, new BigDecimal("12.33333333")); }
@Test public void stripTrailingZeroes() { Expression expr = new Expression(); expr.numbers.add(new BigDecimal("1")); expr.operators.add(Expression.Operator.DIVIDE); expr.numbers.add(new BigDecimal("8")); BigDecimal result = expr.evaluate(false, 8, RoundingMode.HALF_UP); assertEquals(result, new BigDecimal("0.125")); }