# Calculate arithmetic expression represented by a string, in Java

I saw that interview question online and gave it a try:
Implement a function that gets a string which represents an arithmethic expression: contains only numbers or the the operators: '+', '-', '*', '/'.
The function returns the calculation result of the arithmethic expression which appears in the string.
This need to be done in O(n) run-time (n is the length of the string) and O(1) extra space.

Example:

"1+2*3" -> 7


I succeed in implementing this (based mainly on some code I found online), but I just have one problem: logic is too complicated. So when reviewing the code, please tell me how can I simplify the logic here.

Here is the code:

class ArithmethicalStatments {

private static int applyOperator(char operand, int firstNum, int secondNum){
switch (operand) {
case '*':
firstNum *= secondNum;
break;
case '/':
firstNum /= secondNum;
break;
case '+':
firstNum = secondNum;
break;
case '-':
firstNum = -secondNum;
break;
}

return firstNum;
}

public static int calc(String str){
int sum = 0;
int lastApplyOpRes = 0;
int lastNum = 0;
int len = str.length();
char prevOperator = '+';

for (int i = 0; i < len; i++) {
char c = str.charAt(i);

if (c >= '0' && c <= '9') {
lastNum = lastNum * 10 + c - '0';
continue;
}

lastApplyOpRes = applyOperator(prevOperator, lastApplyOpRes , lastNum);
lastNum = 0;

switch (c) {
case '+':
case '-':
sum += lastApplyOpRes;
lastApplyOpRes = 0;
break;
}

prevOperator = c;
}

lastApplyOpRes = applyOperator(prevOperator, lastApplyOpRes , lastNum);

return sum + lastApplyOpRes;
}
}


In case you want to modify the code- some Junit tests I wrote for your convenience:

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

class ArithmethicalStatmentsTest {

@Test
void testEmpty() {
assertEquals(0, ArithmethicalStatments.calc(""));
}

@Test
void testOneNum() {
assertEquals(5, ArithmethicalStatments.calc("5"));
}

@Test
void testPlus() {
assertEquals(8, ArithmethicalStatments.calc("5+3"));
}

@Test
void testMul() {
assertEquals(15, ArithmethicalStatments.calc("5*3"));
}

@Test
void testMulPlus() {
assertEquals(8, ArithmethicalStatments.calc("2*3+2"));
}

@Test
void testPlusMul() {
assertEquals(11, ArithmethicalStatments.calc("2+3*3"));
}

@Test
void testPlusMulPlus() {
assertEquals(16, ArithmethicalStatments.calc("2+3+3*3+2"));
}

@Test
void testMinus() {
assertEquals(2, ArithmethicalStatments.calc("5-3"));
}

@Test
void testDivision() {
assertEquals(2, ArithmethicalStatments.calc("6/3"));
}

@Test
void testMinusPlus() {
assertEquals(1, ArithmethicalStatments.calc("2-3+2"));
}

@Test
void testPlusDivide() {
assertEquals(5, ArithmethicalStatments.calc("3+4/2"));
}

@Test
void testAll() {
assertEquals(6, ArithmethicalStatments.calc("2-3+3/3+2*3"));
}

}


If your logic is too complicated, why don't you try to separate the concerns. You may create a Parser that will contains more well-named method to parse handle the characters in your stream. This one can either produce an object that is evaluated to produce your result or it can call methods on another class to evaluate each expression as soon as they are found (like the DOM vs SAX parsers).