| 
					
				 | 
			
			
				@@ -10,6 +10,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const fs = require('fs'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const streamToArray = require('stream-to-array'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const mathjs = require('mathjs'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 module.exports = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /** 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -208,4 +209,148 @@ module.exports = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return json; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    isOperator(value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const operatorString = "+-*/()"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return operatorString.indexOf(value) > -1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    evalRpn(rpnQueue) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const getResult = function (num1, num2, opera) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            switch (opera) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                case '+': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return num1 + num2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                case '-': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return num1 - num2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                case '*': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return num1 * num2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                case '/': 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return num1 / num2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                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 ? NaN : result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (err) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return NaN; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    calcExprStr(expr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            const result = mathjs.eval(expr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return result === Infinity ? NaN : result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (err) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return NaN; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 |