无括号表达式求值
- 博主前面发过c语言写的,这次用javascript写还是花了不少时间,还有一些新的体会。
代码收获
- javascript主要一开始给你的是字符串,如果使用pharseint中间有除法除出小数就不好计算了。
- 博主这次搞错逻辑了,一开始以为优先级相同直接入栈,优先级相同也需要弹栈进行运算,这样最后就不会有变号问题,只有优先级高的情况才能入栈,结果就能对了。
- 优先级用二重数组有点麻烦,应该使用字典那种会方便处理。
- 确定好步骤,如果边想边写,改动太多,熟练使用while,大致做个流程图,或者先写个伪代码,把全局步骤写一遍,写出来会很方便。
//入栈 push
//出栈 pop
var nNumstack = []; //数字栈
var oOperastack = []; //操作符栈
//优先级
var priority = [
['+', 0],
['-', 0],
['*', 1],
['/', 1]
];
var stext = '5+5/3-9-2'; //测试语句
console.log(stext);
var iindex = 0;
//入数字栈
function pushnumstack(iindex, stext, nNumstack) {
itext = stext.charAt(iindex);
itext = parseFloat(itext);
if (isNaN(itext) == true) {
throw ("字符不是数字:" + itext);
} else {
nNumstack.push(itext);
}
}
//入操作栈
function pushopstack(iindex, stext, oOperastack, priority) {
itext = stext.charAt(iindex);
var sig = 0;
for (var i = 0; i < priority.length; i++) {
if (itext == priority[i][0]) {
sig++;
}
}
if (sig > 0) {
oOperastack.push(itext);
} else {
throw ("操作符未取到s")
}
}
if (nNumstack.length == 0) { //先入第一个数字
pushnumstack(iindex, stext, nNumstack);
iindex++;
} else {
throw ("请清空数组");
}
//入操作符
if (oOperastack.length == 0) {
pushopstack(iindex, stext, oOperastack, priority);
iindex++;
} else {
throw ("请清空数组");
}
//入下一个操作数
pushnumstack(iindex, stext, nNumstack);
iindex++;
//判断下一个操作符优先级
function compareop(stext, iindex, oOperastack, priority) {
var nextop = stext.charAt(iindex);
var stacklastop = oOperastack[oOperastack.length - 1];
var nextoppy;
var stackoppy;
if (stacklastop == undefined) {
return 1;
}
for (var i = 0; i < priority.length; i++) {
if (priority[i][0] == nextop) {
nextoppy = priority[i][1];
}
if (priority[i][0] == stacklastop) {
stackoppy = priority[i][1];
}
}
if (nextoppy > stackoppy) {
return 1; //下一个优先级大于栈内
} else {
if (nextoppy == stackoppy) {
return 0; //等于栈内优先级
} else {
return -1; //小于栈内
}
}
}
//进行判断
sigpy = compareop(stext, iindex, oOperastack, priority);
//如果1,,压栈,如果-1,0,把数字栈2个数字和操作栈1个操作符弹出进行计算,值重新入数字栈,操作符入栈
function judgeflow(stext, iindex, oOperastack, nNumstack, priority, sigpy) {
var res;
if (sigpy > 0) {
pushopstack(iindex, stext, oOperastack, priority);
iindex++;
pushnumstack(iindex, stext, nNumstack);
iindex++;
return iindex;
} else {
num1 = nNumstack.pop();
num2 = nNumstack.pop();
ops = oOperastack.pop();
num1 = parseFloat(num1);
num2 = parseFloat(num2);
switch (ops) {
case "+":
{
res = num1 + num2;
break
};
case "-":
{
res = num2 - num1;
break;
}
case "*":
{
res = num2 * num1;
break
};
case "/":
{
res = num2 / num1;
break
};
default:
throw ("操作符错误", ops);
}
nNumstack.push(res);
return iindex;
}
}
//进行判断
iindex = judgeflow(stext, iindex, oOperastack, nNumstack, priority, sigpy);
//判断iindex是否等于length,不等说明还要继续
while (iindex < stext.length) {
sigpy = compareop(stext, iindex, oOperastack, priority);
iindex = judgeflow(stext, iindex, oOperastack, nNumstack, priority, sigpy);
}
//进行出栈计算 最后会剩一个结果
while (oOperastack.length > 0) {
var res;
num1 = nNumstack.pop();
num2 = nNumstack.pop();
ops = oOperastack.pop();
num1 = parseFloat(num1);
num2 = parseFloat(num2);
ops2 = oOperastack[oOperastack.length - 1];
switch (ops) {
case "+":
{
res = num1 + num2;
break
};
case "-":
{
res = num2 - num1;
break;
}
case "*":
{
res = num2 * num1;
break
};
case "/":
{
res = num2 / num1;
break
};
default:
throw ("操作符错误");
}
nNumstack.push(res);
}
console.log(nNumstack);
5+5/3*6+5*7
[ 50 ]
5+5/3-9-2
[ -4.333333333333333 ]