簡單四則運算及表達式校驗

簡單四則運算及表達式校驗和轉換工具類,僅供參考。
完整工具類請往個人github項目bee.jsgit

//簡單四則運算
ElementaryArithmeticUtils = {
        //運算符優先級
        operatorPrecedence: {
            '+': 0,
            '-': 0,
            '*': 1,
            '×': 1,
            '÷': 1,
            '\/': 1
        },
        //運算符
        operator: {
            '+': '+',
            '-': '-',
            '*': '*',
            '×': '*',
            '÷': '/',
            '\/': '/'
        },
        //加法
        add: function(operandLeft, operandRight) {
            var operand1 = operandLeft.toString();
            var operand2 = operandRight.toString();
            var decimalPlace1 = operand1.indexOf('.') >= 0 ? operand1.split('.')[1].length : 0;
            var decimalPlace2 = operand2.indexOf('.') >= 0 ? operand2.split('.')[1].length : 0;
            var multiple = Math.pow(10, Math.max(decimalPlace1, decimalPlace2));
            return(operandLeft * multiple + operandRight * multiple) / multiple;
        },
        //減法
        subtract: function(operandLeft, operandRight) {
            var operand1 = operandLeft.toString();
            var operand2 = operandRight.toString();
            var decimalPlace1 = operand1.indexOf('.') >= 0 ? operand1.split('.')[1].length : 0;
            var decimalPlace2 = operand2.indexOf('.') >= 0 ? operand2.split('.')[1].length : 0;
            var multiple = Math.pow(10, Math.max(decimalPlace1, decimalPlace2));
            //toFixed避免多出來小數位,如 11.3-10.12000=1.1800000000000015
            var decimalPlace = (decimalPlace1 >= decimalPlace2) ? decimalPlace1 : decimalPlace2;
            return((operandLeft * multiple - operandRight * multiple) / multiple).toFixed(decimalPlace);
        },
        //乘法
        multiply: function(operandLeft, operandRight) {
            var operand1 = operandLeft.toString();
            var operand2 = operandRight.toString();
            var decimalPlace1 = operand1.indexOf('.') >= 0 ? operand1.split('.')[1].length : 0;
            var decimalPlace2 = operand2.indexOf('.') >= 0 ? operand2.split('.')[1].length : 0;
            var multiple1 = Math.pow(10, decimalPlace1);
            var multiple2 = Math.pow(10, decimalPlace2);
            return((operandLeft * multiple1) * (operandRight * multiple2)) / Math.pow(10, decimalPlace1 + decimalPlace2);
        },
        //除法
        divide: function(operandLeft, operandRight) {
            var operand1 = operandLeft.toString();
            var operand2 = operandRight.toString();
            var decimalPlace1 = operand1.indexOf('.') >= 0 ? operand1.split('.')[1].length : 0;
            var decimalPlace2 = operand2.indexOf('.') >= 0 ? operand2.split('.')[1].length : 0;
            var multiple1 = Math.pow(10, decimalPlace1);
            var multiple2 = Math.pow(10, decimalPlace2);
            return((operandLeft * multiple1) / (operandRight * multiple2)) * Math.pow(10, decimalPlace2 - decimalPlace1);
        },
        //校驗表達式的合法性
        isArithmeticExpression: function(expression) {
            try {
                expression = expression.replace(/÷/g, '/').replace(/×/g, '*');
                var result = eval(expression);
            } catch(e) {
                return false;
            }
            return true;
        },
        //計算
        calculate: function(expression) {
            var value = eval(expression);
            return value;
        },
        //中綴表達式轉後綴表達式
        infixToPostfixExpression: function(expression) {
            expression = Bee.StringUtils.deleteWhitespace(expression);
            expression = this.eliminatePositiveOrNegativeSign(expression);
            var operatorStack = [];
            var resultStack = [];
            var elementArr = expression.match(/[-+\/÷*×()]|(?:[1-9]\d*|0)(?:\.\d+)?/g);
            var size = elementArr.length;
            for(var i = 0; i < size; i++) {
                if(Bee.StringUtils.isNumeric(elementArr[i])) {
                    //若是是數值
                    resultStack.push(elementArr[i]);
                } else {
                    //操做符棧頂元素
                    var operatorStackTopElement = operatorStack.length === 0 ? '' : operatorStack[operatorStack.length - 1];
                    //運算符
                    if(operatorStack.length === 0 || elementArr[i] === '(' || operatorStackTopElement === '(' || this.operatorPrecedence[elementArr[i]] > this.operatorPrecedence[operatorStackTopElement]) {
                        //操做符棧爲空或棧頂元素爲右括號')',或操做符的優先級比棧頂運算符高或相等,直接入棧
                        operatorStack.push(elementArr[i]);
                    } else {
                        //若是是右括號")",則依次彈出操做符棧頂的運算符,並壓入結果棧,直到遇到左括號'('爲止,左右括號不壓入結果棧;
                        if(elementArr[i] === ')') {
                            for(var index = operatorStack.length - 1; index >= 0; index--) {
                                if(operatorStack[index] === '(') {
                                    operatorStack.pop();
                                    break;
                                } else {
                                    resultStack.push(operatorStack.pop());
                                }
                            }
                        } else {
                            //將符號棧頂的運算符彈出並壓入到結果棧中,再次與符號棧中新的棧頂運算符相比較
                            resultStack.push(operatorStack.pop());
                            i--;
                            continue;
                        }
                    }
                }
            }
            //處理操做符棧剩餘的符號        
            if(operatorStack.length > 0) {
                for(var j = operatorStack.length - 1; j >= 0; j--) {
                    resultStack.push(operatorStack.pop());
                }
            }
            //結果返回
            return resultStack.join(' ');
        },
        //中綴表達式轉前綴表達式(結果以空格隔開)
        infixToPrefixExpression: function(expression) {
            expression = Bee.StringUtils.deleteWhitespace(expression);
            expression = this.eliminatePositiveOrNegativeSign(expression);
            var operatorStack = [];
            var resultStack = [];
            var elementArr = expression.match(/[-+\/÷*×()]|(?:[1-9]\d*|0)(?:\.\d+)?/g);
            var size = elementArr.length;
            for(var i = size - 1; i >= 0; i--) {
                if(Bee.StringUtils.isNumeric(elementArr[i])) {
                    //若是是數值
                    resultStack.push(elementArr[i]);
                } else {
                    //操做符棧頂元素
                    var operatorStackTopElement = operatorStack.length === 0 ? '' : operatorStack[operatorStack.length - 1];
                    //運算符
                    if(operatorStack.length === 0 || elementArr[i] === ')' || operatorStackTopElement === ')' || this.operatorPrecedence[elementArr[i]] >= this.operatorPrecedence[operatorStackTopElement]) {
                        //操做符棧爲空或棧頂元素爲右括號')',或操做符的優先級比棧頂運算符高或相等,直接入棧
                        operatorStack.push(elementArr[i]);
                    } else {
                        //若是是左括號"(",則依次彈出操做符棧頂的運算符,並壓入結果棧,直到遇到右括號')'爲止,左右括號不壓入結果棧;
                        if(elementArr[i] === '(') {
                            for(var index = operatorStack.length - 1; index >= 0; index--) {
                                if(operatorStack[index] === ')') {
                                    operatorStack.pop();
                                    break;
                                } else {
                                    resultStack.push(operatorStack.pop());
                                }
                            }
                        } else {
                            //將符號棧頂的運算符彈出並壓入到結果棧中,再次與符號棧中新的棧頂運算符相比較
                            resultStack.push(operatorStack.pop());
                            i++;
                            continue;
                        }

                    }
                }
            }
            //處理操做符棧剩餘的符號        
            if(operatorStack.length > 0) {
                for(var j = operatorStack.length - 1; j >= 0; j--) {
                    resultStack.push(operatorStack.pop());
                }
            }
            //結果返回
            return resultStack.reverse().join(' ');
        },
        //解決正負號問題-1轉爲0-1;+1轉爲0+1
        eliminatePositiveOrNegativeSign: function(expression) {
            return expression.replace(/(\(|^)([-+])/g, '$10$2');
        },
        //把中綴表達式轉爲前綴表達式,再計算
        calculateByPrefixExpression: function(expression) {
            var elementArr = this.infixToPrefixExpression(expression).split(' ');
            var size = elementArr.length;
            var resultStack = [];
            for(var i = size - 1; i >= 0; i--) {
                if(Bee.StringUtils.isNumeric(elementArr[i])) {
                    //若是是數值
                    resultStack.push(elementArr[i]);
                } else {
                    var operand1 = resultStack.pop();
                    var operand2 = resultStack.pop();
                    var result;
                    switch(elementArr[i]) {
                        case '+':
                            result = Bee.ElementaryArithmeticUtils.add(operand1, operand2);
                            break;
                        case '-':
                            result = Bee.ElementaryArithmeticUtils.subtract(operand1, operand2);
                            break;
                        case '×':
                        case '*':
                            result = Bee.ElementaryArithmeticUtils.multiply(operand1, operand2);
                            break;
                        case '\/':
                        case '÷':
                            result = Bee.ElementaryArithmeticUtils.divide(operand1, operand2);
                            break;
                        default:
                            result = '';
                            alert("The operator 【" + elementArr[i] + "】 is not legal");
                            break;
                    }
                    resultStack.push(result);
                }
            }
            return resultStack;
        },
        //把中綴表達式轉爲後綴表達式,再計算
        calculateByPostfixExpression: function(expression) {
            var elementArr = this.infixToPostfixExpression(expression).split(' ');
            var size = elementArr.length;
            var resultStack = [];
            for(var i = 0; i < size; i++) {
                if(Bee.StringUtils.isNumeric(elementArr[i])) {
                    //若是是數值
                    resultStack.push(elementArr[i]);
                } else {
                    var operand1 = resultStack.pop();
                    var operand2 = resultStack.pop();
                    var result;
                    switch(elementArr[i]) {
                        case '+':
                            result = Bee.ElementaryArithmeticUtils.add(operand2, operand1);
                            break;
                        case '-':
                            result = Bee.ElementaryArithmeticUtils.subtract(operand2, operand1);
                            break;
                        case '×':
                        case '*':
                            result = Bee.ElementaryArithmeticUtils.multiply(operand2, operand1);
                            break;
                        case '\/':
                        case '÷':
                            result = Bee.ElementaryArithmeticUtils.divide(operand2, operand1);
                            break;
                        default:
                            result = '';
                            alert("The operator 【" + elementArr[i] + "】 is not legal");
                            break;
                    }
                    resultStack.push(result);
                }
            }
            return resultStack;
        },
        //橫式計算
        horizontalCalculation: function(expression) {
            expression = Bee.StringUtils.deleteWhitespace(expression);
            expression = this.eliminatePositiveOrNegativeSign(expression);
            var result = expression;
            while(expression.indexOf('(') >= 0) {
                expression = expression.replace(/\([^()]+\)/g, function(matchStr) {
                    return eval(matchStr);
                });
                result += '=' + expression;
            }
            while(expression.indexOf('[') >= 0) {
                expression = expression.replace(/\[[^\[\]]+\]/g, function(matchStr) {
                    return eval(matchStr);
                });
                result += '=' + expression;
            }
            while(expression.indexOf('{') >= 0) {
                expression = expression.replace(/\{[^{}]+\}/g, function(matchStr) {
                    return eval(matchStr);
                });
                result += '=' + expression;
            }
            var pattern = /(?:[1-9]\d*|0)(?:\.\d+)?[*/](?:[1-9]\d*|0)(?:\.\d+)?/;
            while(expression.indexOf('*') >= 0 || expression.indexOf('/') >= 0) {
                expression = expression.replace(pattern, function(matchStr, index) {
                    return eval(matchStr);
                });
                result += '=' + expression;
            }
            if(/[-+*/]/.test(expression)) {
                result += '=' + eval(expression);
            }
            return result;
        },
        //豎式計算
        verticalCalculation: function(expression) {
            var result = this.horizontalCalculation(expression);
            return result.replace(/=/g, "\n$&");
        }
    };
相關文章
相關標籤/搜索