这几天也在学习 Javascript,前几日师傅给了一篇关于解析四则运算表达式和算法的文章,说四则运算很常用让我好好看看,再让编写代码看看最终结果。
首先我看了代码了解了两个关于算术或逻辑公式的表示法:中缀表示法以及逆波兰表示法,也学习了四则运算的实际转换过程(此定义在原文有详细解释)。
原文:http://www.jb51.net/article/53537.htm
然后我看了作者写的代码,自己分析看明白后,再加了些代码。在这个过程中巩固学习了关于堆栈的知识以及栈(后进先出)和队列(先进先出)方法。
以下代码就是自认为比较完整的代码:
首先判断加减乘除的优先级,* 和 / 的优先级高于 + 和 - :
1 function isOperator(value) { 2 var operatorString = "+-*/()"; 3 return operatorString.indexOf(value) > -1 4 } 5 6 function getPRioraty(value) { 7 switch (value) { 8 case '+': 9 case '-':10 return 1;11 case '*':12 case '/':13 return 2;14 default:15 return 0;16 }17 }18 19 //判断加减乘除的优先级20 function prioraty(o1, o2) { 21 return getPrioraty(o1) <= getPrioraty(o2);22 }
定义输入、输出栈以及输出队列,循环逐个添加到输入栈的末尾,之后处理符号和数字,当找到 "(" 和 ")" 时特殊处理:
1 function dal2Rpn(exp) { 2 //输入栈 3 var inputStack = []; 4 //输出栈 5 var outputStack = []; 6 //输出队列 7 var outputQueue = []; 8 9 for (var i = 0, len = exp.length; i < len; i++) {10 var cur = exp[i];11 if (cur != ' ') {12 inputStack.push(cur); //+-*/() 数字,逐个添加到末尾13 }14 }15 16 //处理字符和数字17 while (inputStack.length > 0) {18 19 //shift 顶部取得一项后移除,unshift 顶部推入20 cur = inputStack.shift();21 22 //如果是符号 --> + - * / ( )23 if (isOperator(cur)) {24 if (cur == '(') {25 //push 从尾部推入一项26 outputStack.push(cur);27 } else if (cur == ')') {28 //pop 从尾部取得一项,之后移出29 var po = outputStack.pop();30 while (po != '(' && outputStack.length > 0) {31 outputQueue.push(po);32 po = outputStack.pop();33 }34 if (po != '(') {35 throw "错误:没有匹配";36 }37 } else { //符号时,处理 + - * /38 while (prioraty(cur, outputStack[outputStack.length - 1])39 && outputStack.length > 0) {40 outputQueue.push(outputStack.pop());41 }42 outputStack.push(cur);43 }44 } else { //是数字的时候,推入数字45 outputQueue.push(new Number(cur));46 }47 }48 49 if (outputStack.length > 0) {50 if (outputStack[outputStack.length - 1] == ')'51 || outputStack[outputStack.length - 1] == '(') {52 throw "错误:没有匹配";53 }54 while (outputStack.length > 0) {55 outputQueue.push(outputStack.pop());56 }57 }58 return evalRpn(outputQueue);59 }
定义 evalRpn() 函数,输出堆栈的长度不小于2的时候,进行计算:
1 function evalRpn(queue) { 2 var outputStack = []; 3 while (queue.length > 0) { 4 var cur = queue.shift(); 5 6 if (!isOperator(cur)) { 7 outputStack.push(cur); 8 } else { 9 //如果输出堆栈长度小于 210 if (outputStack.length < 2) {11 throw "无效堆栈长度";12 }13 var second = outputStack.pop();14 var first = outputStack.pop();15 16 outputStack.push(getResult(first, second, cur));17 }18 }19 20 if (outputStack.length != 1) {21 throw "不正确的运算";22 } else {23 return outputStack[0];24 }25 }
进行加减乘除计算之后,对其值进行操作,当浮点数的小数位超过两位时,只保留两位小数点:
1 function getResult(first, second, operator){ 2 var result = 0; 3 switch (operator) { 4 case '+': 5 result = first + second; 6 break; 7 case '-': 8 result = first - second; 9 break;10 case '*':11 result = first * second;12 break;13 case '/':14 result = first / second;15 break;16 default:17 return 0;18 }19 20 //浮点数的小数位超过两位时,只保留两位小数点21 function formatFloat(f, digit) {22 //pow(10,n) 为 10 的 n 次方23 var m = Math.pow(10, digit);24 return parseInt(f * m, 10) / m;25 }26 return (formatFloat(result, 2));27 }
输入要计算的表达式,计算结果 ( 结果得到 -0.6 ):
1 var result=dal2Rpn('( 1 + 2 ) * (( 3 - 4 ) / 5)');2 console.log(result); //输出结果
新闻热点
疑难解答