2011-02-04 61 views
2

我现在试图通过让用户输入公式来在HTML5 <canvas>上绘制公式。这很好,通过eval();然而,^意味着在JavaScript中按位异或,它应该意味着'在公式中的权力'。重写公式字符串以用Math.pow替换^ b(a,b)

所以基本上我不得不重写一些像x^4Math.pow(x, 4)。我想出了使用正则表达式。这一次却只能在一定程度上:

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

它改写x^4Math.pow(x, 4),但对于更先进的配方这一出错。例如,2 + x^4被重写为Math.pow(2 + x, 4),而它当然应该是2 + Math.pow(x, 4)。而且,如果指数在其周围有括号,例如2^(x+1) + 3,当然应该改写为Math.pow(2, x+1) + 3而不是Math.pow(2, x+1 + 3)

我将如何去重写这个,只有正确的部分被放入pow函数?我真的不知道从哪里开始,所以任何提示将不胜感激。

+0

您的正则表达式需要更加彻底以适应系数。你应该让它检查变量前后的空白,并且通过注入`*`来分隔变量的系数。您还必须实现`()` – 2011-02-04 18:24:17

+1

[RegEx for a^b而不是pow(a,b)]的可能重复所指示的相同语法规则(http://stackoverflow.com/questions/4777685/正则表达式为ab-instead-of-powa-b) – 2011-02-04 18:26:43

回答

7

这是一个棘手的问题。你在这里讨论的是一个表达式解析器。

您可能想看看Jison,它旨在帮助人们解决这类问题。

正则表达式不是解析字符串化的最好方法。 One of Jison's demos正好是你正在寻找什么,在表达式解析方面,让你在函数图形的有趣东西上工作。

3

我怀疑这甚至可以用正则表达式来实现。 JS中的正则表达式不支持递归模式(即使这样做也会非常麻烦),所以对于复杂表达式(如((x + 2) * 3)^(x^(2 * x))),您的运气不佳。

如果您希望能够在表达式上进行这种转换,您可能必须使用适当的标记器和解析器才能使结构脱离它。

1

通常使用lexersparsers而不是正则表达式来处理这种类型的问题。由于数学表达式的操作顺序,您需要了解整个表达式(及其所有部分),而不仅仅是部分的权力。我不知道该解析器通常用于JavaScript中,但似乎ANTLR具有生成的Javascript解析器目标:http://www.antlr.org/wiki/display/ANTLR3/ANTLR3JavaScriptTarget

1
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克(2^3 + 1)^ 5)^(9-2^3)“)); (Math.Pow(x,2))-2),2)+ Math.pow((3)Math.pow((3)Math.pow((f(Math.pow pow(2,3)+1),5)),(9-Math.pow(2,3)))

  2. 你的数学表达式必须有平衡的开放和闭合圆括号(有效表达式)。

  3. 你可以用你想要的任何函数名替换“Math.pow”。

  4. 我已经更换所有括号做到了这一点,从最内层到最外层,与非数学文本(“_joker _0" ,” _joker _1" ,等等)。最后,我分层解析所有这些字符串,以取代非括号表达式中的插入符号。

相关问题