63 lines
2.0 KiB
TypeScript
63 lines
2.0 KiB
TypeScript
|
|
function toRPN(expression:string) {
|
|
let outputQueue = '';
|
|
let operatorStack = [];
|
|
let operators = {
|
|
'+': {precedence: 2, associativity: 'Left'},
|
|
'-': {precedence: 2, associativity: 'Left'},
|
|
'*': {precedence: 3, associativity: 'Left'},
|
|
'/': {precedence: 3, associativity: 'Left'}
|
|
};
|
|
|
|
expression = expression.replace(/\s+/g, '');
|
|
let expression2 = expression.split(/([\+\-\*\/])/).filter(token => token);
|
|
|
|
expression2.forEach(token => {
|
|
if (parseFloat(token) || token === '0') {
|
|
outputQueue += token + ' ';
|
|
} else if ('+-*/'.includes(token)) {
|
|
while (operatorStack.length > 0 &&
|
|
((operators[token].associativity === 'Left' &&
|
|
operators[token].precedence <= operators[operatorStack[operatorStack.length - 1]].precedence) ||
|
|
(operators[token].associativity === 'Right' &&
|
|
operators[token].precedence < operators[operatorStack[operatorStack.length - 1]].precedence))) {
|
|
outputQueue += operatorStack.pop() + ' ';
|
|
}
|
|
|
|
operatorStack.push(token);
|
|
}
|
|
});
|
|
|
|
while (operatorStack.length > 0) {
|
|
outputQueue += operatorStack.pop() + ' ';
|
|
}
|
|
|
|
return outputQueue.trim();
|
|
}
|
|
|
|
function calculateRPN(expression:string) {
|
|
let stack:number[] = [];
|
|
|
|
expression.split(' ').forEach(token => {
|
|
if (parseFloat(token) || token === '0') {
|
|
stack.push(parseFloat(token));
|
|
} else {
|
|
let [b, a] = [stack.pop(), stack.pop()];
|
|
switch (token) {
|
|
case '+': stack.push(a + b); break;
|
|
case '-': stack.push(a - b); break;
|
|
case '*': stack.push(a * b); break;
|
|
case '/': stack.push(a / b); break;
|
|
}
|
|
}
|
|
});
|
|
|
|
return stack.pop();
|
|
}
|
|
|
|
export function calcString(args:string) {
|
|
const expression = toRPN(args);
|
|
const evaluated = calculateRPN(expression);
|
|
return evaluated
|
|
}
|