1

简单四则运算及表达式校验和转换工具类,仅供参考。
完整工具类请往我的github项目bee.js

//简单四则运算
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$&");
        }
    };
    

老鼠拧刀满街找猫
2.6k 声望1.4k 粉丝

java攻城狮