资讯专栏INFORMATION COLUMN

简单四则运算及表达式校验

nanfeiyan / 3207人阅读

简单四则运算及表达式校验和转换工具类,仅供参考。
完整工具类请往我的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, "
$&");
        }
    };
    

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84597.html

相关文章

  • 函数式编程与面向对象编程[5]:编程的本质

    摘要:函数式编程与面向对象编程编程的本质之剑目录编程的本质读到两篇文章写的不错综合摘录一下复合是编程的本质函数式程序员在洞察问题方面会遵循一个奇特的路线。在面向对象编程中,类或接口的声明就是表面。 函数式编程与面向对象编程[5]:编程的本质 之剑 2016.5.6 01:26:31 编程的本质 读到两篇文章,写的不错, 综合摘录一下 复合是编程的本质 函数式程序员在洞察问题方面会遵循...

    miracledan 评论0 收藏0
  • 慕课网_《探秘Spring AOP》学习总结

    时间:2017年09月03日星期日说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com 教学源码:https://github.com/zccodere/s...学习源码:https://github.com/zccodere/s... 第一章:课程介绍 1-1 面向切面 课程章节 概览 AOP使用 AOP原理 AOP开源运用 课程实战 课程总结 面向切面编程是一种...

    Tony_Zby 评论0 收藏0
  • 前端计划——JavaScript正则达式快速入门

    摘要:前言正则表达式时处理字符串中常用的手法,本文以简单的方式,快速展示了中正则相关的基础知识点。文末还提供了几个简单的正则相关面试题。接下来是正则部分,注意后面的并不匹配,也就是比如,实际匹配的值是和,在和后面加上,就完成了预期。 前言:正则表达式时处理字符串中常用的手法,本文以简单的方式,快速展示了JavaScript中正则相关的基础知识点。文末还提供了几个简单的正则相关面试题。个人总结...

    Xufc 评论0 收藏0
  • 身份证号码的正则达式验证详解(JavaScript,Regex)

    摘要:简言在做用户实名验证时,常会用到身份证号码的正则表达式及校验方案。身份证号码说明居民身份证号码,正确正式的称谓应该是公民身份号码。也有说法表述开头是外国人取得中国身份证号码的前两位编码,但本人并未得到证实。 简言 在做用户实名验证时,常会用到身份证号码的正则表达式及校验方案。本文列举了两种验证方案,大家可以根据自己的项目实际情况,选择适合的方案。 showImg(https://seg...

    laznrbfe 评论0 收藏0
  • php性能怎么优化?php性能优化安全策略

    摘要:性能问题一般不会超过占整个项目性能的,一般在。内置函数的性能优劣。几乎与在函数中调用局部变量的速度相当。递增一个全局变量要比递增一个局部变量慢倍。类似的方法调用所花费的时间接近于次的局部变量递增操作。 php性能怎么优化?性能是网站运行是否良好的关键因素, 网站的性能与效率影响着公司的运营成本及长远发展,编写出高质高效的代码是我们每个开发人员必备的素质,也是我们良好...

    番茄西红柿 评论0 收藏2637

发表评论

0条评论

最新活动
阅读需要支付1元查看
<