patternjavaMinor
A (late) Simple Calculator
Viewed 0 times
simplecalculatorlate
Problem
As I was looking through my past questions, I noticed my really old calculator question (here and here). Considering it looked like a huge mess, I decided to rewrite it. Coincidentally, the April 2015 Community Challenge was to implement a simple calculator. It might be a bit late, but here it is:
```
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
public class Calculator {
private static final Pattern NUMBER_PATTERN = Pattern
.compile("\\d+(\\.\\d+)?");
public static double calculate(String equation) {
return calculate(equation, Operation.getLastInPrecedence());
}
private static double calculate(String equation, Operation currentOp) {
Operation nextOp = currentOp.getPreviousInPrecedence();
if (NUMBER_PATTERN.matcher(equation).matches()) {
return Double.parseDouble(equation);
}
String[] equationParts = equation.split("\\s*"
+ Pattern.quote(Character.toString(currentOp.getSymbol()))
+ "\\s*");
double result;
if (nextOp == null) {
// Last operation
result = Math.pow(Integer
.parseInt(equationParts[equationParts.length - 2]), Integer
.parseInt(equationParts[equationParts.length - 1]));
for (int i = equationParts.length - 3; i >= 0; i--) {
result = Math.pow(Integer.parseInt(equationParts[i]), result);
}
} else {
result = calculate(equationParts[0], nextOp);
for (int i = 1; i operations = new HashMap<>();
static {
operations.put(ADD.precedence, ADD);
operations.put(SUBTRACT.precedence, SUBTRACT);
operations.put(MULTIPLY.precedence, MULTIPLY);
operations.put(DIVIDE.precedence, DIVIDE);
operations.put(POW.precedence, POW);
}
private final char symbol;
private final int precedence;
private Operation(char symbol, int
```
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
public class Calculator {
private static final Pattern NUMBER_PATTERN = Pattern
.compile("\\d+(\\.\\d+)?");
public static double calculate(String equation) {
return calculate(equation, Operation.getLastInPrecedence());
}
private static double calculate(String equation, Operation currentOp) {
Operation nextOp = currentOp.getPreviousInPrecedence();
if (NUMBER_PATTERN.matcher(equation).matches()) {
return Double.parseDouble(equation);
}
String[] equationParts = equation.split("\\s*"
+ Pattern.quote(Character.toString(currentOp.getSymbol()))
+ "\\s*");
double result;
if (nextOp == null) {
// Last operation
result = Math.pow(Integer
.parseInt(equationParts[equationParts.length - 2]), Integer
.parseInt(equationParts[equationParts.length - 1]));
for (int i = equationParts.length - 3; i >= 0; i--) {
result = Math.pow(Integer.parseInt(equationParts[i]), result);
}
} else {
result = calculate(equationParts[0], nextOp);
for (int i = 1; i operations = new HashMap<>();
static {
operations.put(ADD.precedence, ADD);
operations.put(SUBTRACT.precedence, SUBTRACT);
operations.put(MULTIPLY.precedence, MULTIPLY);
operations.put(DIVIDE.precedence, DIVIDE);
operations.put(POW.precedence, POW);
}
private final char symbol;
private final int precedence;
private Operation(char symbol, int
Solution
I have doubts about your unit tests — did you run them?
In addition, your test coverage is spotty.
As for the calculator itself, I think it would be worthwhile to implement support for parentheses as well. Otherwise, there's no way to override the order of operations.
- The test runner can't run your test unless it is
public.
- The class name
Testcollides with theorg.junit.Testannotation.
- For all the tests, I got
java.lang.AssertionError: Use assertEquals(expected, actual, delta) to compare floating-point numbers— you need to specify a tolerance.
In addition, your test coverage is spotty.
- You mentioned your concern about right-to-left associativity for the
^operator, so why didn't you test for that?
- Is
1 + 1 / 2equal to 1.5 (standard precedence rules) or 1.0 (cheap calculator)?
- Is
12 / 2 / 3equal to 2.0 (standard associativity rules)? Your code evaluates it to 3.0, failing this test.
As for the calculator itself, I think it would be worthwhile to implement support for parentheses as well. Otherwise, there's no way to override the order of operations.
Context
StackExchange Code Review Q#90850, answer score: 7
Revisions (0)
No revisions yet.