evaluateExpression function
Evaluates an arithmetic expression and returns the result as a double
.
The expression
parameter is a string that represents the arithmetic
expression to evaluate.
Example:
void main() {
// Evaluate an arithmetic expression and print the result.
final result = evaluateExpression('2 * (3 + 4) / 5');
print(result); // Output: 2.80
}
Returns the result of the arithmetic expression as a double
.
Implementation
double evaluateExpression(String expression) {
int i = 0;
if (expression.isEmpty) {
throw Exception('Invalid expression');
}
// A recursive function that parses the expression and
// returns the result as a Decimal.
double parseExpression() {
final values = <double>[]; // A stack to store numeric values.
final operators = <String>[]; // A stack to store operators.
double lastNonOperatorValue = 1.0;
// Iterate through the expression.
while (i < expression.length) {
if (expression[i] == ' ') {
i++; // Ignore spaces.
} else if (isOperator(expression[i])) {
// If the current character is an operator.
if (isNegativeUnaryOperator(expression, i)) {
// If the current character is a unary operator,
// parse the number with a negative sign.
i++;
int j = i;
while (j < expression.length &&
isCharDigitOrDecimalPointOrPercentage(expression[j])) {
j++;
}
final substring = '-${expression.substring(i, j)}';
var dValue = double.parse(substring.replaceAll('%', ''));
if (isStringPercentage(expression.substring(i, j)) &&
(operators.isEmpty ||
operators.last == '+' ||
operators.last == '-')) {
// Handle percentage operation for '+' or '-' operators.
// Handle percentage operation for '+' or '-' operators.
dValue = lastNonOperatorValue * (dValue / 100);
}
values.add(dValue); // Add the parsed number to the values stack.
lastNonOperatorValue = dValue;
i = j;
} else {
// If the current operator has lower or equal precedence than
// the last operator in the stack, apply the last operator.
while (operators.isNotEmpty &&
precedence(expression[i]) <= precedence(operators.last)) {
applyOperation(operators.removeLast(), values);
}
operators
.add(expression[i]); // Add the current operator to the stack.
i++;
}
} else if (expression[i] == '(') {
// If the current character is an open parenthesis.
i++;
values.add(parseExpression()); // Call parseExpression recursively.
} else if (expression[i] == ')') {
// If the current character is a close parenthesis.
i++;
// Apply all remaining operators in the stack to the values
// in the stack.
while (operators.isNotEmpty) {
applyOperation(operators.removeLast(), values);
}
return values.last; // Return the last value in the stack.
} else {
// If the current character is a digit or a decimal point.
int j = i;
while (j < expression.length &&
isCharDigitOrDecimalPointOrPercentage(expression[j])) {
j++;
}
final substring = expression.substring(i, j);
var dValue = double.parse(substring.replaceAll('%', ''));
if (isStringPercentage(expression.substring(i, j)) &&
(operators.isEmpty ||
operators.last == '+' ||
operators.last == '-')) {
// Handle percentage operation for '+' or '-' operators.
dValue = lastNonOperatorValue * (dValue / 100);
}
values.add(dValue); // Add the parsed number to the values stack.
lastNonOperatorValue = dValue;
i = j;
}
}
// Apply any remaining operators in the stack to the values in the stack.
while (operators.isNotEmpty) {
applyOperation(operators.removeLast(), values);
}
return values.last; // Return the last value in the stack.
}
return parseExpression()
.toDouble(); // Call parseExpression and convert the result to double.
}