开发者

RegEx for a^b instead of pow(a,b)

Here's an interesting one. Anyone have a good RegEx for converting all (first) ^ (second) to Math.pow((first), (second))?

EDIT:

The best I have so far is

s = s.replace(/((?:\d+\.?\d*)|\w+|\((?:(?:[^\(\)]*(?:\([^\(\)]*\)))*)\))\s*\^\s*((?:\d+\.?\d*)|\w+|\((?:(?:[^\(\)]*(?:\([^\(\)]*\)))*)\))/g, 'Math.pow($1, $2)') // replace expression ^ expression with Math.pow($1, $2)

The answers so far are not general enough. They don't cover something like (var1 + var2)^2 let alone (var1 * (var2 + var3))^2

The solution will have to work with parentheses.

You can use strfriend.com 开发者_运维技巧to help visualize the regex as you make it. That's what I've been doing.


This cannot be done with regex (at least not without lots of effort). You have to consider different layers of parenthesis, which can't be handled with a simple regular expression. I suggest to look for a library capable of parsing mathematical expression. Or you'll have to restrict the possible expression to something you can handle with a simple regex.

There is the possibility to define named and balancing capture groups in a regular expression which can be used (backreferenced) in the same regular expression. With this you would have to define the desired subset of the math syntax and both captures for the parameters. I suggest you should not reinvent the wheel and use a JS library.

http://snippets.dzone.com/posts/show/2207


You could use String.replace:

> s = "hello 2^3 pow!"
> s.replace(/(\d+)\^(\d+)/, "Math.pow($1, $2)")
"hello Math.pow(2, 3) pow!"


Assuming you want to convert source files or something like that, take a perl script running over your source files and use Math::Expression::Evaluator::Parser. From the synopsis:

use Math::Expression::Evaluator::Parser;

my $exp = '2 + a * 4';
my $ast = Math::Expression::Evaluator::Parser::parse($exp, {});
# $ast is now something like this:
# $ast = ['+',
#          2,
#         ['*',
#          ['$', 'a'],
#          4
#         ]
#        ];

Looks like it can handle exponentiations easily. So the AST in your case would be something like:

# $ast = ['^',
#         base,
#         exp
#        ];

You could build the desired expression 'Math.pow(base, exp)' by (recursively) reassemble a string from the 'base' and 'exp' subtrees.

If you want to implement a calculator in JavaScript then you need of course a JavaScript-Parser or you could rely on a server-backend implemented using Math::Expression::Evaluator.


The bad news: regular expressions won't cut it (as many answers indicate), you will need to write a parser for this.

The good news: you can relatively easily do this yourself in almost any language by writing a recursive descent parser. You should of course reuse existing code as much as possible, but coding a recursive descent parser yourself (and seeing how you encode precedence rules) can be recommended purely for the enlightening experience.

Pick up any book on compiler construction and read the first few chapters on parsing. Let me recommend this freely available book by Niklaus Wirth, look for 4.1 "The method of recursive descent".


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)")); 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))).

  2. Your math expression must be valid, with well balanced opened and closed parentheses.

  3. You can replace Math.pow with any function name you want.

  4. I've done this by replacing all parentheses, from the most inner to the most outer, with non-math texts (___joker___0, ___joker___1, etcetera). At the end I parse all these strings hierarchically, to replace carets on non-parentheses expressions.


Take a look at Jison, a Javascript parser generator.

In particular, check out their calculator demo

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜