JavaScript 四则运算:加减乘除

这几天也在学习 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                     //如果输出堆栈长度小于 2
10                     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);   //输出结果

 

转载于:https://www.cnblogs.com/weixinyuai/p/4280036.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值