`
绿窗明月
  • 浏览: 3514 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

js解析字符串四则表达式

阅读更多

记得大学时学到过解析字符串四则表达式,好像是数据结构里的课程。具体的内容都忘掉了,也找不到数据机构课本,就在网上找了些相关资料,现在用js实现一下。具体思路是把普通的表达式转换为前置或者后置表达式,然后通过转换后的表达式来计算。

当然,是有需求了才这么做。在js中通过eval或着Function都可以实现类似功能。通过测试,在非ie浏览器中解析表达式的效率比eval(Function)高,在ie中正好相反。由于客户的大多使用的是ie,就采用了Function的方式。

代码如下:

 

(function () {
    var priority = {
        '*': 2,
        '/': 2,
        '+': 1,
        '-': 1
    }, strExpression2arrExpression = function (expression) {//字符串转换为数组
        var arr = [];
        for (var i = 0, s, t, l = expression.length; i < l; i++) {
            s = expression.charAt(i);
            if (isNaN(s)&&s!='.') {
                arr.push(s);
            } else {
                t = s;
                while (i < l) {
                    s = expression.charAt(i + 1);
                    if (!isNaN(s)||s=='.') {
                        t += s;
                        i++;
                    } else {
                        break;
                    }
                }
                arr.push(parseFloat(t));
            }
        }
        return arr;
    }, infixExpression2prefixExpression = (function () { //将中缀表达式转换为前缀表达式
        var s1 = [], s2 = [], operator = function (o) {
            var last = s1[s1.length - 1];
            if (s1.length == 0 || last == ')') {
                s1.push(o);
            } else if (priority[o] >= priority[last]) {
                s1.push(o);
            } else {
                s2.push(s1.pop());
                operator(o);
            }
        };
        return function (arrExpression) {
            s1.length = 0;
            s2.length = 0;
            for (var i = arrExpression.length - 1, o; i >= 0; i--) {
                o = arrExpression[i]
                if (!isNaN(o)) {
                    s2.push(o);
                } else {
                    if (o == '+' || o == '-' || o == '*' || o == '/') {//运算符
                        operator(o)
                    } else {//括号
                        if (o == ')') {//右括号
                            s1.push(o)
                        } else {//左括号
                            var s = s1.pop();
                            while (s != ')') {
                                s2.push(s);
                                s = s1.pop();
                            }
                        }
                    }
                }
            }
            if (s1.length > 0) {
                while (s1[0] != undefined) {
                    s2.push(s1.pop())
                }
            }
            s1.length = 0;
            return s2.slice();
        }
    })(), computePrefixExpression = (function () {
        var s1 = [], result;
        return function (prefixExpression) {
            s1.length = 0;
            //计算
            while (prefixExpression.length > 0) {
                var o = prefixExpression.shift();
                if (!isNaN(o)) {
                    s1.push(o);
                } else {
                    switch (o) {
                        case '+':
                        {
                            result = s1.pop() + s1.pop();
                            break;
                        }
                        case '-':
                        {
                            result = s1.pop() - s1.pop();
                            break;
                        }
                        case '*':
                        {
                            result = s1.pop() * s1.pop();
                            break;
                        }
                        case '/':
                        {
                            result = s1.pop() / s1.pop();
                            break;
                        }
                    }
                    s1.push(result);
                }
                //console.log(s2,s1)
            }
            //console.log(s1)
            return s1[0];
        }
    })();
    window.compute = function (expression) {
        //console.log(strExpression2arrExpression(expression))
        //console.log(infixExpression2prefixExpression(strExpression2arrExpression(expression)).reverse())
        return computePrefixExpression(infixExpression2prefixExpression(strExpression2arrExpression(expression)));
    }
})();



 

测试结果如下:

 

console.log(compute('100/(1.5+10/((2+3)*4)-5)*10'))
eval('console.log(100/(1.5+10/((2+3)*4)-5)*10)')

 

-333.33333333333337
 
-333.33333333333337

 

本文参考了antineutrino的文章《前缀、中缀、后缀表达式》,讲得很不错,具体原理大家可以学习一下。

有兴趣了可以看看本人的一个在线demo



 

分享到:
评论

相关推荐

    把字符串转化为表达式

    这些库提供了构建和执行表达式树的能力,能够对字符串表达式进行编译和安全执行,同时提供了更丰富的数学函数支持。 总的来说,通过`Interop.MSScriptControl.dll`库,C#开发者可以方便地将字符串转换为可执行的...

    js解析cron表达式

    资源为js文件,下载后直接用script标签引入,需要解析时调用该js第一个方法,参数为cron定时器表达式字符串,例如:translateCRONToChinese("0 0 12 */1 * ?");

    js将字符串转成正则表达式的实现方法

    标题和描述中提到的“js将字符串转成正则表达式的实现方法”主要涉及的是如何将一个包含正则表达式语法的字符串转化为可执行的正则对象。 在JavaScript中,有两种主要的方法可以实现这一目标: 1. **使用`new ...

    字符串转表达式,进行加减乘除等逻辑运算

    在计算机科学中,字符串转表达式并执行加减乘除等逻辑运算是一项常见的任务,尤其在解析用户输入或处理计算式时。这个过程通常涉及到两个关键步骤:中缀表达式到后缀表达式的转换(也称为逆波兰表示法)以及后缀...

    利用正则表达式巧妙解析度分秒格式字符串

    在编程领域,正则表达式是一种强大的文本处理工具,它能帮助我们进行复杂的字符串匹配、查找、替换和解析。在本话题中,我们将探讨如何利用C#中的正则表达式来巧妙地解析度分秒格式的字符串,将其转换为统一的度数...

    【JS相关问题处理】 正则表达式解决JS取值被过滤掉引号的方法

    在JavaScript编程中,正则表达式是不可或缺的一部分,它用于处理字符串、匹配模式以及执行复杂的文本操作。在本文中,我们将深入探讨如何使用正则表达式来解决在JS中取值时引号被过滤掉的问题。这个问题通常发生在从...

    Java 中运行字符串表达式的方法

    `:解析一个字符串表达式,得到一个“字符串表达式运行器” —— Runner,然后调用其 `run(/* data */)` 方法运行并得到结果。 RunnerUtil 的语法及运算规则与 Java 和 JavaScript 兼容,相同符号具有相同或相似的...

    js分割字符串 js分割字符串 js分割字符串

    JavaScript中的字符串分割是一个重要的操作,尤其在处理用户输入或数据解析时。本文将详细探讨JavaScript中六种不同的字符串分割方法,以及它们各自的特点和应用场景。 1. `slice(start, end)`: `slice()`方法从...

    js替换字符串

    ### JavaScript字符串替换技术详解 在Web开发中,JavaScript(简称JS)作为一种强大的客户端脚本语言,在处理DOM元素、样式及动态交互方面具有不可替代的作用。本文将深入探讨JS中的字符串替换功能及其应用案例,...

    regexgen生成与一组字符串匹配的正则表达式

    总的来说,`regexgen` 是JavaScript开发者处理正则表达式问题的一个实用工具,尤其在处理大量字符串匹配需求时,能显著提高开发效率和代码质量。通过深入理解其原理和使用方法,开发者可以更好地应对复杂的文本处理...

    JavaScript截取中文字符串

    4. **添加省略号**:如果`hasDot`参数为真且原始字符串长度大于指定长度,则在截取后的字符串末尾添加省略号。 #### 四、代码详解 ```javascript function subString(str, len, hasDot) { var newLength = 0; ...

    js eval函数使用,js对象和字符串互转实例.docx

    在JavaScript中,`eval()`函数是一个强大的工具,它能够将字符串形式的JavaScript代码解析并执行。这使得动态生成和执行代码成为可能,但也因此带来了潜在的安全风险。 **基本语法**: ```javascript eval...

    sizeyunsuan.rar_四则表达式

    1. **解析表达式**:将字符串形式的四则表达式转换为可执行的结构。这可能涉及到创建一个抽象语法树(AST),其中每个节点代表一个操作或数值,节点间的连接表示运算的顺序。 2. **处理运算符优先级**:根据运算符...

    js字符串操作大全

    根据给定的文件信息,我们将深入探讨JavaScript(简称JS)中的字符串操作,这些操作对于处理文本数据至关重要。本文将详细解析文件中提到的部分扩展方法,包括去除字符串两侧空格、获取字符串的左侧、右侧或中间部分...

    js日期字符串互转

    在JavaScript中,日期和字符串之间的转换是常见的操作,特别是在处理用户输入、数据存储或与服务器交互时。本文将详细介绍如何在JavaScript中进行日期与字符串的互转,并提供一个实际示例来验证日期的有效性。 首先...

    js json字符串转对象

    当JSON字符串被解析为JavaScript对象时,这些类型会被适当地转换: - 数字(如30)保持不变,仍然是JavaScript的Number类型。 - 字符串(如"John")保持不变,仍然是JavaScript的String类型。 - 布尔值(如true...

    work2_分割字符串_字符串处理_

    在Python中,可以使用内置的 `split()` 方法进行字符串分割,而在JavaScript中,可以使用 `split()` 函数或者正则表达式进行分割。 总的来说,理解并熟练掌握字符串处理技巧对于任何级别的程序员都至关重要。无论是...

Global site tag (gtag.js) - Google Analytics