简体   繁体   English

重写公式字符串以用Math.pow(a,b)替换^ b

[英]Rewrite formula string to replace a^b with Math.pow(a, b)

I'm at the moment trying to plot formulas on HTML5 <canvas> by letting the user put in a formula. 我正在尝试通过让用户输入公式来在HTML5 <canvas>上绘制公式。 This works great through eval() ; 这通过eval()很好用; however, the ^ means bitwise XOR in Javascript, while it should mean 'to the power of' in a formula. 但是, ^表示Javascript中的按位异或,而它应该表示公式中的'幂'。

So basically I'd have to rewrite something like x^4 to Math.pow(x, 4) . 所以基本上我必须将x^4重写为Math.pow(x, 4) I came up with using regular expressions. 我想出了使用正则表达式。 This one however only works to a certain extent: 然而,这只在一定程度上起作用:

"x^4".replace(/(.*)\\^(.*)/g, "Math.pow($1, $2)")

It does rewrite x^4 to Math.pow(x, 4) , but for more advanced formulas this goes wrong. 它确实将x^4重写为Math.pow(x, 4) ,但是对于更高级的公式,这是错误的。 For example, 2 + x^4 is rewritten as Math.pow(2 + x, 4) , while it should of course be 2 + Math.pow(x, 4) . 例如, 2 + x^4被重写为Math.pow(2 + x, 4) ,而它当然应该是2 + Math.pow(x, 4) Moreover, if the exponent has brackets around it, eg 2^(x+1) + 3 , it should be rewritten to Math.pow(2, x+1) + 3 instead of Math.pow(2, x+1 + 3) , of course. 此外,如果指数在其周围有括号,例如2^(x+1) + 3 ,则应将其重写为Math.pow(2, x+1) + 3而不是Math.pow(2, x+1 + 3) ,当然。

How would I go about rewriting this so that only the correct parts are put into the pow function? 我将如何重写这一点,以便只将正确的部分放入pow功能? I really do not see where to start, so any tips would be greatly appreciated. 我真的没有看到从哪里开始,所以任何提示将不胜感激。

This is a tricky one. 这是一个棘手的问题。 What you're talking about here is an expression parser. 你在这里谈论的是一个表达式解析器。

You might want to take a look at Jison , which is designed to help people solve this type of problem. 您可能想看看Jison ,它旨在帮助人们解决此类问题。

Regular expressions aren't really the best way to do parsing of tokenized strings. 正则表达式实际上不是解析标记化字符串的最佳方法。 One of Jison's demos is precisely what you're looking for, in terms of expression parsing, leaving you to work on the fun stuff of function graphing. 在表达式解析方面,Jison的一个演示 正是您所寻找的,让您开始学习函数图形的有趣功能。

I doubt this is even doable with regex. 我怀疑这甚至可以用正则表达式来实现。 The regex flavor in JS doesn't support recursive patterns (and it would be extremely cumbersome to do it even with that), so you're out of luck with complex expressions such as ((x + 2) * 3)^(x ^ (2 * x)) . JS中的正则表达式风格不支持递归模式(即使使用它也会非常麻烦),所以你对复杂表达式运气不利,例如((x + 2) * 3)^(x ^ (2 * x))

If you want to be able to do transformations like this on the expression, you'll probably have to use a proper tokenizer and parser in order to get the structure out of it. 如果你希望能够在表达式上进行这样的转换,你可能必须使用正确的标记器和解析器才能从中获取结构。

    var caretReplace = function(_s) {
    if (_s.indexOf("^") > -1) {
        var tab = [];
        var powfunc="Math.pow";
        var joker = "___joker___";
        while (_s.indexOf("(") > -1) {
            _s = _s.replace(/(\([^\(\)]*\))/g, function(m, t) {
                tab.push(t);
                return (joker + (tab.length - 1));
            });
        }

        tab.push(_s);
        _s = joker + (tab.length - 1);
        while (_s.indexOf(joker) > -1) {
            _s = _s.replace(new RegExp(joker + "(\\d+)", "g"), function(m, d) {
                return tab[d].replace(/(\w*)\^(\w*)/g, powfunc+"($1,$2)");
            });
        }
    }
    return _s;
};
  1. console.log(caretReplace("(3*(f(x^2)-2)^2+1^5-g(2^3+1)^5)^(9-2^3)")); 的console.log(caretReplace( “(3 *(F(X ^ 2)-2)^ 2 + 1 ^ 5克(2 ^ 3 + 1)^ 5)^(9-2 ^ 3)”)); gives : Math.pow((3*Math.pow((f(Math.pow(x,2))-2),2)+Math.pow(1,5)-Math.pow(g(Math.pow(2,3)+1),5)),(9-Math.pow(2,3))) 给出:Math.pow((3 * Math.pow((f(Math.pow(x,2)) - 2),2)+ Math.pow(1,5)-Math.pow(g(Math.pow) (2,3)1),5)),(9-Math.pow(2,3)))

  2. Your math expression must be with well balanced opened and closed parenthesis (valid expression). 您的数学表达式必须具有良好平衡的开括号和闭括号(有效表达式)。

  3. You can replace "Math.pow" by any function name you want. 您可以用您想要的任何函数名替换“Math.pow”。

  4. I've done this by replacing all parenthesis, from the most inner to the most outer, with non-math texts (" _joker _0"," _joker _1", etc...). 我通过用非数学文本(“ _joker _0”,“_ joker _1”等等)替换所有括号,从最内部到最外部,完成了这个。 At the end I parse all theses strings hierarchically, to replace carets on non parenthesis expressions. 最后,我将分层次地解析所有这些字符串,以替换非括号表达式上的插入符号。

Typically this type of problem is approached using lexers and parsers , not regexes. 通常使用词法 分析器解析器来处理这种类型的问题,而不是正则表达式。 Because of the order of operations of the mathematical expressions, you need to understand the whole expression (and all of its parts), not just the power-of portion. 由于数学表达式的操作顺序,您需要理解整个表达式(及其所有部分),而不仅仅是幂的部分。 I am not sure which parsers are generally used for Javascript, but it seems ANTLR has a target for generating Javascript parsers: http://www.antlr.org/wiki/display/ANTLR3/ANTLR3JavaScriptTarget 我不确定哪些解析器通常用于Javascript,但似乎ANTLR有一个生成Javascript解析器的目标: http//www.antlr.org/wiki/display/ANTLR3/ANTLR3JavaScriptTarget

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM