我一直致力于在 JavaScript 中为类实现 Shutting-Yard 算法。
这是我到目前为止的工作:
var userInput = prompt("Enter in a mathematical expression:");
var postFix = InfixToPostfix(userInput);
var result = EvaluateExpression(postFix);
document.write("Infix: " + userInput + "<br/>");
document.write("Postfix (RPN): " + postFix + "<br/>");
document.write("Result: " + result + "<br/>");
function EvaluateExpression(expression)
{
var tokens = expression.split(/([0-9]+|[*+-\/()])/);
var evalStack = [];
while (tokens.length != 0)
{
var currentToken = tokens.shift();
if (isNumber(currentToken))
{
evalStack.push(currentToken);
}
else if (isOperator(currentToken))
{
var operand1 = evalStack.pop();
var operand2 = evalStack.pop();
var result = PerformOperation(parseInt(operand1), parseInt(operand2), currentToken);
evalStack.push(result);
}
}
return evalStack.pop();
}
function PerformOperation(operand1, operand2, operator)
{
switch(operator)
{
case '+':
return operand1 + operand2;
case '-':
return operand1 - operand2;
case '*':
return operand1 * operand2;
case '/':
return operand1 / operand2;
default:
return;
}
}
function InfixToPostfix(expression)
{
var tokens = expression.split(/([0-9]+|[*+-\/()])/);
var outputQueue = [];
var operatorStack = [];
while (tokens.length != 0)
{
var currentToken = tokens.shift();
if (isNumber(currentToken))
{
outputQueue.push(currentToken);
}
else if (isOperator(currentToken))
{
while ((getAssociativity(currentToken) == 'left' &&
getPrecedence(currentToken) <= getPrecedence(operatorStack[operatorStack.length-1])) ||
(getAssociativity(currentToken) == 'right' &&
getPrecedence(currentToken) < getPrecedence(operatorStack[operatorStack.length-1])))
{
outputQueue.push(operatorStack.pop())
}
operatorStack.push(currentToken);
}
else if (currentToken == '(')
{
operatorStack.push(currentToken);
}
else if (currentToken == ')')
{
while (operatorStack[operatorStack.length-1] != '(')
{
if (operatorStack.length == 0)
throw("Parenthesis balancing error! Shame on you!");
outputQueue.push(operatorStack.pop());
}
operatorStack.pop();
}
}
while (operatorStack.length != 0)
{
if (!operatorStack[operatorStack.length-1].match(/([()])/))
outputQueue.push(operatorStack.pop());
else
throw("Parenthesis balancing error! Shame on you!");
}
return outputQueue.join(" ");
}
function isOperator(token)
{
if (!token.match(/([*+-\/])/))
return false;
else
return true;
}
function isNumber(token)
{
if (!token.match(/([0-9]+)/))
return false;
else
return true;
}
function getPrecedence(token)
{
switch (token)
{
case '^':
return 9;
case '*':
case '/':
case '%':
return 8;
case '+':
case '-':
return 6;
default:
return -1;
}
}
function getAssociativity(token)
{
switch(token)
{
case '+':
case '-':
case '*':
case '/':
return 'left';
case '^':
return 'right';
}
}
到目前为止它工作正常。如果我给它:
((5+3) * 8)
它将输出:
中缀:((5+3) * 8)
后缀 (RPN):5 3 + 8 *
结果:64
但是,我正在努力实现一元运算符,因此我可以执行以下操作:
(( -5 +3) * 8)
实现一元运算符(否定等)的最佳方法是什么?另外,是否有人对处理浮点数有任何建议?
最后一件事,如果有人看到我在 JavaScript 中做任何奇怪的事情,请告诉我。这是我的第一个 JavaScript 程序,我还不习惯。