这是一个允许多个操作数并尊重操作顺序的答案,与当前此处的任何其他答案不同。
import java.util.Arrays;
import java.util.List;
public class Expression {
private List<Integer> operands;
private List<Character> operators;
public Expression(List<Integer> operands, List<Character> operators) {
this.operands = operands;
this.operators = operators;
}
public Expression subExpression(int fromIndex, int toIndex) {
return new Expression(
operands.subList(fromIndex, toIndex),
operators.subList(fromIndex, toIndex - 1));
}
private int rightMost(char operator) {
return operators.lastIndexOf(operator);
}
public double evaluate() {
if (operands.size() == 1) {
return operands.get(0).doubleValue();
}
if (rightMost('+') > -1){
return subExpression(0, rightMost('+') + 1).evaluate()
+ subExpression(rightMost('+') + 1, operands.size()).evaluate();
}
if (rightMost('-') > -1){
return subExpression(0, rightMost('-') + 1).evaluate()
- subExpression(rightMost('-') + 1, operands.size()).evaluate();
}
if (rightMost('*') > -1){
return subExpression(0, rightMost('*') + 1).evaluate()
* subExpression(rightMost('*') + 1, operands.size()).evaluate();
}
if (rightMost('/') > -1){
return subExpression(0, rightMost('/') + 1).evaluate()
/ subExpression(rightMost('/') + 1, operands.size()).evaluate();
}
return 0;
}
@Override
public String toString() {
StringBuilder toReturn = new StringBuilder();
for (int index = 0; index < operands.size(); index++){
toReturn.append(operands.get(index));
toReturn.append(" ");
toReturn.append(
index == operators.size() ? "=" : operators.get(index));
toReturn.append(" ");
}
toReturn.append(evaluate());
return toReturn.toString();
}
public static Expression makeRandom(
int minimum, int maximum, int numberOfOperands) {
Integer[] operands = new Integer[numberOfOperands];
Character[] operators = new Character[numberOfOperands - 1];
for (int index = 0; index < numberOfOperands; index++) {
operands[index] = minimum
+ (int)(Math.random() * (maximum - minimum + 1));
}
for (int index = 0; index < numberOfOperands - 1; index++) {
operators[index] = "+-*/".charAt((int)(Math.random() * 4));
}
return new Expression(Arrays.asList(operands), Arrays.asList(operators));
}
public static void main (String[] args){
System.out.println(makeRandom(1, 10, 6));
System.out.println(new Expression(
Arrays.asList(1, 2, 3), Arrays.asList('+', '*')));
}
}
这main
只是为了进行快速而肮脏的测试。这是一次运行的输出。如您所见,1 + 2 * 3
给出了正确的答案 - 当前此页面上的其他答案都没有正确答案。
10 / 5 / 6 * 9 + 9 * 1 = 12.0
1 + 2 * 3 = 7.0
我已经evaluate
返回double
以避免整数除法的任何令人讨厌的惊喜。如有必要,这很容易改变。此外,这里没有错误处理 - 有一些方法应该对其参数进行一些错误处理,并且确实应该做一些关于捕获除以零的事情。
这是通过将表达式拆分为更小的子表达式,递归地评估每个子表达式,然后将它们重新组合在一起来实现的。神奇之处在于evaluate
方法中的操作顺序。由于这些原因,必须按此顺序处理不同的运算符。
+
必须在之前考虑-
,以便a - b + c
解析为(a - b) + c
,而不是a - (b + c)
。
*
必须在之前考虑/
,以便a / b * c
解析为(a / b) * c
,而不是a / (b * c)
。
+
并且-
两者都必须在*
和之前考虑/
,以便首先评估*
和。/
- 减法必须从右到左进行,因此
a - b - c
解析为(a - b) - c
,而不是a - (b - c)
。
- 除法必须从右到左工作,因此
a / b / c
解析为(a / b) / c
,而不是a / (b / c)
。
- 加法和乘法可以从左到右或从右到左进行,但是在编写了
rightMost
方法之后,从右到左进行它们是有意义的。