Arithmetic evaluation: Difference between revisions
Content deleted Content added
→{{header|Haskell}}: Added a type signature to expr |
→{{header|Java}}: code cleanup, consistent indentation |
||
Line 2,611: | Line 2,611: | ||
<lang java>import java.util.Stack; |
<lang java>import java.util.Stack; |
||
public class ArithmeticEvaluation |
public class ArithmeticEvaluation { |
||
{ |
|||
public |
public interface Expression { |
||
BigRational eval(); |
|||
public static enum BinaryOperator |
|||
{ |
|||
ADD('+', 1) { |
|||
public BigRational eval(BigRational leftValue, BigRational rightValue) { return leftValue.add(rightValue); } |
|||
}, |
|||
SUB('-', 1) { |
|||
public BigRational eval(BigRational leftValue, BigRational rightValue) { return leftValue.subtract(rightValue); } |
|||
}, |
|||
MUL('*', 2) { |
|||
public BigRational eval(BigRational leftValue, BigRational rightValue) { return leftValue.multiply(rightValue); } |
|||
}, |
|||
DIV('/', 2) { |
|||
public BigRational eval(BigRational leftValue, BigRational rightValue) { return leftValue.divide(rightValue); } |
|||
}; |
|||
public final char symbol; |
|||
public final int precedence; |
|||
BinaryOperator(char symbol, int precedence) |
|||
{ |
|||
this.symbol = symbol; |
|||
this.precedence = precedence; |
|||
} |
} |
||
public enum Parentheses {LEFT} |
|||
public abstract BigRational eval(BigRational leftValue, BigRational rightValue); |
|||
} |
|||
public enum BinaryOperator { |
|||
ADD('+', 1), |
|||
public static class BinaryExpression |
|||
SUB('-', 1), |
|||
{ |
|||
MUL('*', 2), |
|||
public Object leftOperand = null; |
|||
DIV('/', 2); |
|||
public BinaryOperator operator = null; |
|||
public Object rightOperand = null; |
|||
public final char symbol; |
|||
public final int precedence; |
|||
public BinaryExpression(Object leftOperand, BinaryOperator operator, Object rightOperand) |
|||
{ |
|||
BinaryOperator(char symbol, int precedence) { |
|||
this.leftOperand = leftOperand; |
|||
this. |
this.symbol = symbol; |
||
this. |
this.precedence = precedence; |
||
} |
|||
public BigRational eval(BigRational leftValue, BigRational rightValue) { |
|||
switch (this) { |
|||
case ADD: |
|||
return leftValue.add(rightValue); |
|||
case SUB: |
|||
return leftValue.subtract(rightValue); |
|||
case MUL: |
|||
return leftValue.multiply(rightValue); |
|||
case DIV: |
|||
return leftValue.divide(rightValue); |
|||
} |
|||
throw new IllegalStateException(); |
|||
} |
|||
public static BinaryOperator forSymbol(char symbol) { |
|||
for (BinaryOperator operator : values()) { |
|||
if (operator.symbol == symbol) { |
|||
return operator; |
|||
} |
|||
} |
|||
throw new IllegalArgumentException(String.valueOf(symbol)); |
|||
} |
|||
} |
} |
||
public |
public static class Number implements Expression { |
||
private final BigRational number; |
|||
{ |
|||
BigRational leftValue = (leftOperand instanceof BinaryExpression) ? ((BinaryExpression)leftOperand).eval() : (BigRational)leftOperand; |
|||
public Number(BigRational number) { |
|||
BigRational rightValue = (rightOperand instanceof BinaryExpression) ? ((BinaryExpression)rightOperand).eval() : (BigRational)rightOperand; |
|||
this.number = number; |
|||
return operator.eval(leftValue, rightValue); |
|||
} |
|||
@Override |
|||
public BigRational eval() { |
|||
return number; |
|||
} |
|||
@Override |
|||
public String toString() { |
|||
return number.toString(); |
|||
} |
|||
} |
} |
||
public static class BinaryExpression implements Expression { |
|||
public String toString() |
|||
public final Expression leftOperand; |
|||
{ return "(" + leftOperand + " " + operator.symbol + " " + rightOperand + ")"; } |
|||
public final BinaryOperator operator; |
|||
} |
|||
public final Expression rightOperand; |
|||
public static void createNewOperand(BinaryOperator operator, Stack<Object> operands) |
|||
public BinaryExpression(Expression leftOperand, BinaryOperator operator, Expression rightOperand) { |
|||
{ |
|||
this.leftOperand = leftOperand; |
|||
Object rightOperand = operands.pop(); |
|||
this.operator = operator; |
|||
operands.push(new BinaryExpression(operands.pop(), operator, rightOperand)); |
|||
this.rightOperand = rightOperand; |
|||
return; |
|||
} |
|||
public static Object createExpression(String inputString) |
|||
{ |
|||
int curIndex = 0; |
|||
boolean afterOperand = false; |
|||
Stack<Object> operands = new Stack<Object>(); |
|||
Stack<Object> operators = new Stack<Object>(); |
|||
inputStringLoop: |
|||
while (curIndex < inputString.length()) |
|||
{ |
|||
int startIndex = curIndex; |
|||
char c = inputString.charAt(curIndex++); |
|||
if (Character.isWhitespace(c)) |
|||
continue; |
|||
if (afterOperand) |
|||
{ |
|||
if (c == ')') |
|||
{ |
|||
Object operator = null; |
|||
while (!operators.isEmpty() && ((operator = operators.pop()) != Parentheses.LEFT)) |
|||
createNewOperand((BinaryOperator)operator, operands); |
|||
continue; |
|||
} |
} |
||
afterOperand = false; |
|||
@Override |
|||
for (BinaryOperator operator : BinaryOperator.values()) |
|||
{ |
public BigRational eval() { |
||
BigRational leftValue = leftOperand.eval(); |
|||
BigRational rightValue = rightOperand.eval(); |
|||
{ |
|||
return operator.eval(leftValue, rightValue); |
|||
while (!operators.isEmpty() && (operators.peek() != Parentheses.LEFT) && (((BinaryOperator)operators.peek()).precedence >= operator.precedence)) |
|||
} |
|||
createNewOperand((BinaryOperator)operators.pop(), operands); |
|||
operators.push(operator); |
|||
@Override |
|||
public String toString() { |
|||
return "(" + leftOperand + " " + operator.symbol + " " + rightOperand + ")"; |
|||
} |
} |
||
throw new IllegalArgumentException(); |
|||
} |
|||
if (c == '(') |
|||
{ |
|||
operators.push(Parentheses.LEFT); |
|||
continue; |
|||
} |
|||
afterOperand = true; |
|||
while (curIndex < inputString.length()) |
|||
{ |
|||
c = inputString.charAt(curIndex); |
|||
if (((c < '0') || (c > '9')) && (c != '.')) |
|||
break; |
|||
curIndex++; |
|||
} |
|||
operands.push(BigRational.valueOf(inputString.substring(startIndex, curIndex))); |
|||
} |
} |
||
private static void createNewOperand(BinaryOperator operator, Stack<Expression> operands) { |
|||
while (!operators.isEmpty()) |
|||
Expression rightOperand = operands.pop(); |
|||
{ |
|||
Expression leftOperand = operands.pop(); |
|||
operands.push(new BinaryExpression(leftOperand, operator, rightOperand)); |
|||
if (operator == Parentheses.LEFT) |
|||
throw new IllegalArgumentException(); |
|||
createNewOperand((BinaryOperator)operator, operands); |
|||
} |
} |
||
Object expression = operands.pop(); |
|||
public static Expression parse(String input) { |
|||
if (!operands.isEmpty()) |
|||
int curIndex = 0; |
|||
boolean afterOperand = false; |
|||
return expression; |
|||
Stack<Expression> operands = new Stack<>(); |
|||
} |
|||
Stack<Object> operators = new Stack<>(); |
|||
while (curIndex < input.length()) { |
|||
public static void main(String[] args) |
|||
int startIndex = curIndex; |
|||
{ |
|||
char c = input.charAt(curIndex++); |
|||
String[] testExpressions = { "2+3", "2+3/4", "2*3-4", "2*(3+4)+5/6", "2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10", "2*-3--4+-.25" }; |
|||
for (String testExpression : testExpressions) |
|||
if (Character.isWhitespace(c)) |
|||
{ |
|||
continue; |
|||
Object expression = createExpression(testExpression); |
|||
System.out.println("Input: \"" + testExpression + "\", AST: \"" + expression + "\", eval=" + (expression instanceof BinaryExpression ? ((BinaryExpression)expression).eval() : expression)); |
|||
if (afterOperand) { |
|||
if (c == ')') { |
|||
Object operator; |
|||
while (!operators.isEmpty() && ((operator = operators.pop()) != Parentheses.LEFT)) |
|||
createNewOperand((BinaryOperator) operator, operands); |
|||
continue; |
|||
} |
|||
afterOperand = false; |
|||
BinaryOperator operator = BinaryOperator.forSymbol(c); |
|||
while (!operators.isEmpty() && (operators.peek() != Parentheses.LEFT) && (((BinaryOperator) operators.peek()).precedence >= operator.precedence)) |
|||
createNewOperand((BinaryOperator) operators.pop(), operands); |
|||
operators.push(operator); |
|||
continue; |
|||
} |
|||
if (c == '(') { |
|||
operators.push(Parentheses.LEFT); |
|||
continue; |
|||
} |
|||
afterOperand = true; |
|||
while (curIndex < input.length()) { |
|||
c = input.charAt(curIndex); |
|||
if (((c < '0') || (c > '9')) && (c != '.')) |
|||
break; |
|||
curIndex++; |
|||
} |
|||
operands.push(new Number(BigRational.valueOf(input.substring(startIndex, curIndex)))); |
|||
} |
|||
while (!operators.isEmpty()) { |
|||
Object operator = operators.pop(); |
|||
if (operator == Parentheses.LEFT) |
|||
throw new IllegalArgumentException(); |
|||
createNewOperand((BinaryOperator) operator, operands); |
|||
} |
|||
Expression expression = operands.pop(); |
|||
if (!operands.isEmpty()) |
|||
throw new IllegalArgumentException(); |
|||
return expression; |
|||
} |
|||
public static void main(String[] args) { |
|||
String[] testExpressions = { |
|||
"2+3", |
|||
"2+3/4", |
|||
"2*3-4", |
|||
"2*(3+4)+5/6", |
|||
"2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10", |
|||
"2*-3--4+-.25"}; |
|||
for (String testExpression : testExpressions) { |
|||
Expression expression = parse(testExpression); |
|||
System.out.printf("Input: \"%s\", AST: \"%s\", value=%s%n", testExpression, expression, expression.eval()); |
|||
} |
|||
} |
} |
||
} |
|||
}</lang> |
}</lang> |
||
{{out}} |
{{out}} |
||
<pre>Input: "2+3", AST: "(2 + 3)", |
<pre>Input: "2+3", AST: "(2 + 3)", value=5 |
||
Input: "2+3/4", AST: "(2 + (3 / 4))", |
Input: "2+3/4", AST: "(2 + (3 / 4))", value=11/4 |
||
Input: "2*3-4", AST: "((2 * 3) - 4)", |
Input: "2*3-4", AST: "((2 * 3) - 4)", value=2 |
||
Input: "2*(3+4)+5/6", AST: "((2 * (3 + 4)) + (5 / 6))", |
Input: "2*(3+4)+5/6", AST: "((2 * (3 + 4)) + (5 / 6))", value=89/6 |
||
Input: "2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10", AST: "((2 * ((3 + ((4 * 5) + ((6 * 7) * 8))) - 9)) * 10)", |
Input: "2 * (3 + (4 * 5 + (6 * 7) * 8) - 9) * 10", AST: "((2 * ((3 + ((4 * 5) + ((6 * 7) * 8))) - 9)) * 10)", value=7000 |
||
Input: "2*-3--4+-.25", AST: "(((2 * -3) - -4) + -1/4)", |
Input: "2*-3--4+-.25", AST: "(((2 * -3) - -4) + -1/4)", value=-9/4</pre> |
||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |