私はShunting-YardアルゴリズムをJavaScript用に実装しています。ここで単項演算子を受け入れるようにShunting-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)
Postfixの私はそれを与える場合(RPN):5 3 + 8 *
結果:64
は、しかし、私は単項operatoを実装することに苦労しています単項演算子(否定、など)を実装するための最良の方法だろう何
((-5 3)* 8)
:ので、私は次のようにRSができますか?また、誰も浮動小数点数を処理するための任意の提案を持っていますか?
誰かが私にJavaScriptで奇妙なことをしているのを見たら、私に知らせてください。これは私の最初のJavaScriptプログラムであり、まだ慣れていません。
しかし、何にイテレータですsinやsqrtのような他の演算子を使用している場合は?本当に罪悪感(3 + 4)のようなことをするのは難しいことです。 –
これまでのところ問題がある限り、それは問題の一部ではありません。:) – ultrajohn
私はちょうど最近この実装を行いました。 – Makach