Calculate expression of a given string.
This calculator parses given String expression and calculates its result. Input string may contain the following:
- Positive integers
- Negative integers
- Sum +
- Difference -
- Multiplication *
- Division /
- Opening and closing brackets (are processed as equal) ( ), { } and [ ]
- Spaces
Fill AdvancedCalculator
with expression that should be evaluated:
String result = new AdvancedCalculator().evaluate("2 + 2");
Evaluated result is expected to contain one of the following:
- Decimal number as a String
- Unexpected symbols error. Like:
"Given expression '%s' contains unexpected symbols."
- Unbalanced parenthesis error. Like:
"Given expression '%s' has unbalanced parenthesis."
.
For examples please check StringCalculatorTest or other project tests for more details.
- Prepare expression for being parsed
- Remove all spaces
- Replace all different kinds of brackets with parenthesis
- Verify given expression is valid
- Ensure no extra symbols were provided
- Ensure parentheses are balanced
- Parse expression into more specific operations:
- Convert each symbol into a List of undefined operations.
For example:
1+-1
will become1,+,-,1
. - Parse all negative numbers into
NumberOperation
. For example:1,+,-,1
will become1,+,-1
. - Parse all positive numbers into
NumberOperation
. - Surround multiplication and division operands with parentheses to simplify further parsing.
For example
1,+,-1,*,2
will become1,+,(,-1,*,2,)
. - Group all operands to simplify further parsing.
For example
1,+,(,-1,*,2,)
will become(,1,+,(,-1,*,2,),)
. - Parse received expression from right to left* into specific operations as a tree.
For example
(,1,+,(,-1,*,2,),)
will become:+ / \ 1 * / \ -1 2
- Convert each symbol into a List of undefined operations.
For example:
- Evaluate received operations tree into expression result
* Note:
We can parse from left to right. This will result into the following cases:
1. expression like "10 - 2 + 4 - 5 + 6 = 13" will be calculated as "10 - (2 + (4 - (5 + 6))) = 15"
1. expression like "10 - 2 - 4 + 5 - 6 = 3" will be calculated as "10 - (2 - (4 + (5 - 6))) = 11"
There are 2 possible options to overcome this issue:
1. Update parsed results afterwards and invert all operands to the left of each difference operand
1. Parse from right to left.
Second option is easier and simplifies the code:
1. expression like "10 - 2 + 4 - 5 + 6 = 13" will be calculated as "((((10 - 2) + 4) - 5) + 6) = 13"
1. expression like "10 - 2 - 4 + 5 - 6 = 3" will be calculated as "((((10 - 2) - 4) + 5) - 6) = 3"
Code changes should not break existing tests.
Tests are triggered during project build. Build status should be BUILD SUCCESS
mvn clean test
Test coverage is not necessary 100%, but should be high:
Can be checked through IDE. Current coverage is:
- Class: 95%
- Method: 100%
- Line: 98%
Test mutation should be at high level:
mvn -DwithHistory org.pitest:pitest-maven:mutationCoverage
Current score is:
- Line Coverage = 99%
- Mutation Coverage = 93%