我正在尝试通过让用户输入公式来在HTML5 <canvas>
上绘制公式。这通过eval()
很有效;但是,^
表示Javascript中的按位XOR,而它应该表示公式中的'幂'。
所以基本上我必须重写像x^4
到Math.pow(x, 4)
之类的东西。我想出了使用正则表达式。然而,这只在某种程度上起作用:
"x^4".replace(/(.*)\^(.*)/g, "Math.pow($1, $2)")
它会将x^4
重写为Math.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 :(得分:7)
这是一个棘手的问题。你在这里谈论的是一个表达式解析器。
您可能需要查看Jison,其目的是帮助人们解决此类问题。
正则表达式实际上不是解析标记化字符串的最佳方法。在表达式解析方面,One of Jison's demos 正是正在寻找你正在寻找的东西,让你继续处理函数图形的有趣内容。
答案 1 :(得分:3)
我怀疑这甚至可以用正则表达式来实现。 JS中的正则表达式风格不支持递归模式(即使使用它也会非常麻烦),因此您对((x + 2) * 3)^(x ^ (2 * x))
等复杂表达式运气不佳。
如果你想在表达式上进行这样的转换,你可能必须使用正确的标记器和解析器才能从中获取结构。
答案 2 :(得分:1)
通常使用lexers和parsers来处理此类问题,而不是正则表达式。由于数学表达式的操作顺序,您需要理解整个表达式(及其所有部分),而不仅仅是幂的部分。我不确定哪些解析器通常用于Javascript,但似乎ANTLR有一个生成Javascript解析器的目标:http://www.antlr.org/wiki/display/ANTLR3/ANTLR3JavaScriptTarget
答案 3 :(得分: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;
};
的console.log(caretReplace(“(3 *(F(X ^ 2)-2)^ 2 + 1 ^ 5克(2 ^ 3 + 1)^ 5)^(9-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)))
您的数学表达式必须使用平衡的左右括号(有效表达式)。
您可以用您想要的任何功能名称替换“Math.pow”。
我通过用非数学文本(“ _joker _0”,“ _joker _1“等等......)最后,我将分层次地解析所有这些字符串,以替换非括号表达式上的插入符号。