I have a input like
string input = \"14 + 2 * 32 / 60 + 43 - 7 + 3 - 1 + 0 * 7 + 87 - 32 / 34\";
// up to 10MB string size
int result = Calc(input); // 11
Here is a Java fun fact. I implemented the same thing in Java and it runs about 20 times faster than Mirai Mann implementation in C#. On my machine 100M chars input string took about 353 milliseconds.
Below is the code that creates and tests the result.
Also, note that while it's a good Java/C# performance tester this is not an optimal solution. A better performance can be achieved by multithreading it. It's possible to calculate portions of the string and then combine the result.
public class Test {
public static void main(String...args){
new Test().run();
}
private void run() {
long startTime = System.currentTimeMillis();
Random random = new Random(123);
int result = 0;
StringBuilder input = new StringBuilder();
input.append(random.nextInt(99) + 1);
while (input.length() < 100_000_000){
int value = random.nextInt(100);
switch (random.nextInt(4)){
case 0:
input.append("-");
result -= value;
break;
case 1: // +
input.append("+");
result += value;
break;
case 2:
input.append("*");
result *= value;
break;
case 3:
input.append("/");
while (value == 0){
value = random.nextInt(100);
}
result /= value;
break;
}
input.append(value);
}
String inputData = input.toString();
System.out.println("Test created in " + (System.currentTimeMillis() - startTime));
startTime = System.currentTimeMillis();
int testResult = test(inputData);
System.out.println("Completed in " + (System.currentTimeMillis() - startTime));
if(result != testResult){
throw new Error("Oops");
}
}
private int test(String inputData) {
char[] input;
try {
Field val = String.class.getDeclaredField("value");
val.setAccessible(true);
input = (char[]) val.get(inputData);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new Error(e);
}
int result = 0;
int startingI = 1;
{
char c = input[0];
if (c >= '0' && c <= '9') {
result += c - '0';
c = input[1];
if (c >= '0' && c <= '9') {
result += (c - '0') * 10;
startingI++;
}
}
}
for (int i = startingI, length = input.length, value=0; i < length; i++) {
char operation = input[i];
i++;
char c = input[i];
if(c >= '0' && c <= '9'){
value += c - '0';
c = input[i + 1];
if(c >= '0' && c <= '9'){
value = value * 10 + (c - '0');
i++;
}
}
switch (operation){
case '-':
result -= value;
break;
case '+':
result += value;
break;
case '*':
result *= value;
break;
case '/':
result /= value;
break;
}
value = 0;
}
return result;
}
}
When you read the code then you can see that I used a small hack when converting the string to a char array. I mutated the string in order to avoid additional memory allocations for the char array.