| 
					
				 | 
			
			
				@@ -122,5 +122,156 @@ const ZhCalc = (function () { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return value ? new Decimal(value).toDecimalPlaces(decimal).toNumber() : null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return {add, sub, mul, div, round, isNonZero: zhBaseCalc.isNonZero} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const ExprCalc = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * 判断value是否是四则运算符 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * @param {String} value - 判断字符串 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * @return {Boolean} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        isOperator(value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const operatorString = "+-*/()"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return operatorString.indexOf(value) > -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * Rpn解析栈 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * @param exp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * @returns {Array} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        parse2Rpn(exp) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const getPriority = function (value){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                switch(value){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case '+': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case '-': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case '*': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case '/': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const priority = function (o1, o2){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return getPriority(o1) <= getPriority(o2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const inputStack = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const outputStack = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const outputQueue = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for (let i = 0, len = exp.length; i < len; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const cur = exp[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (cur !== ' ' ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    inputStack.push(cur); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let num = '', isNumPre = false, isOperatorPre = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            while(inputStack.length > 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const cur = inputStack.shift(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (this.isOperator(cur) && !(cur === '-' && !isNumPre)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (isNumPre) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        outputQueue.push(parseFloat(num)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        num = ''; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (cur === '(') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        outputStack.push(cur); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } else if (cur === ')') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        let po = outputStack.pop(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        while (po !== '(' && outputStack.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            outputQueue.push(po); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            po = outputStack.pop(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (po !== '(') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            throw "error: unmatched ()"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        while(priority(cur, outputStack[outputStack.length - 1]) && outputStack.length > 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            outputQueue.push(outputStack.pop()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        outputStack.push(cur); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    isNumPre = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    isOperatorPre = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    num = num + cur; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    isNumPre = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    isOperatorPre = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (inputStack.length === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        outputQueue.push(parseFloat(num)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (outputStack.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (outputStack[outputStack.length - 1] === ')' || outputStack[outputStack.length - 1] === '(') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    throw "error: unmatched ()"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                while (outputStack.length > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    outputQueue.push(outputStack.pop()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return outputQueue; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * 计算Rpn解析栈 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * @param rpnQueue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * @returns {*} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        evalRpn(rpnQueue) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const getResult = function (num1, num2, opera) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                switch (opera) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case '+': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return add(num1, num1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case '-': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return sub(num1, num2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case '*': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return mul(num1, num2, 10); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    case '/': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        return div(num1, num2, 10); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        throw '参数错误'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const outputStack = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            while(rpnQueue.length > 0){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                const cur = rpnQueue.shift(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!this.isOperator(cur)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    outputStack.push(cur); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (outputStack.length < 2) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        throw "unvalid stack length"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    const sec = outputStack.pop(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    const fir = outputStack.pop(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    outputStack.push(getResult(fir, sec, cur)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (outputStack.length !== 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw "unvalid expression"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return outputStack[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * 解析四则运算字符串并计算 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * @param {String} expr 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         * @returns 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        calcExprStrRpn(expr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (!isNaN(Number(expr))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return Number(expr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    const rpnArr = this.parse2Rpn(expr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    const result = this.evalRpn(rpnArr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return result === Infinity ? null : result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } catch (err) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return {add, sub, mul, div, round, isNonZero: zhBaseCalc.isNonZero, calcExpr: ExprCalc} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 })(); 
			 |