使用JavaScript将指数LaTeX语法转换为PHP的pow()

时间:2014-08-05 09:13:25

标签: javascript regex latex

我想用JS来转换嵌套的指数LaTeX表达式,例如

2^{3^{4^5}}

到PHP' pow()语法

pow(2,pow(3,pow(4,5)))

我知道JS不支持递归RegExp。表达式是等式的一部分,所以我希望解决方案能够像

那样工作
\frac{3}{9}+\frac{2^{\sqrt{4^2}}}{6}

应该输出

\frac{3}{9}+\frac{pow(2,\sqrt{pow(4,2)})}{6} 
像@ AbcAeffchen的解决方案一样。

我不需要转换非指数部分。

注意:解决方案不得要求使用PHP 5.6,它引入了**运算符

3 个答案:

答案 0 :(得分:4)

一个丑陋的黑客,

> foo
'2,(3^(4^5))'
> var foo = "2^(3^(4^5))".replace(/\^/g, ",");
undefined
> foo
'2,(3,(4,5))'
> var bar = foo.replace(/(\d,)(?=[^\d])/g, "$1pow");
undefined
> var foobar = bar.replace(/^(.*)$/, "pow($1)")
undefined
> foobar
'pow(2,pow(3,pow(4,5)))'

答案 1 :(得分:2)

尝试我写的这个功能。它只使用普通的字符串函数,所以它稍长一点 基本上它的工作原理如下

  • 找到^
  • 的第一个匹配项
  • 找到属于基础的^之前的部分
  • 找到属于指数的^之后的部分
  • 在指数和指数
  • 之后的部分上递归调用函数
  • 将所有部分放在一起。

所以它在JavaScript中看起来:



function convertLatexPow(str)
{
    // contains no pow
    var posOfPow = str.indexOf('^');
    if(posOfPow == -1)
        return str;

    var head = str.substr(0,posOfPow);
    var tail = str.substr(posOfPow+1);

    // find the beginning of pow
    var headLen = posOfPow;
    var beginning = 0;
    var counter;
    if(head[headLen-1] == '}')      // find the opening brace
    {
        counter = 1;
        for(i = headLen-2; i >= 0; i--)
        {
            if(head[i] == '}')
                counter++;
            else if(head[i] == '{')
                counter--;

            if(counter == 0)
            {
                beginning = i;
                break;
            }
        }
    }
    else if(head[headLen-1].match('[0-9]{1}'))  // find the beginning of the number
    {
        for(i = headLen-2; i >= 0; i--)
        {
            if(!head[i].match('[0-9]{1}'))
            {
                beginning = i+1;
                break;
            }
        }
    }
    else    // the string looks like ...abc^{..}.. so the basis is only one character ('c' in this case)
        beginning = headLen-1;

    var untouchedHead = head.substr(0,beginning);

    var firstArg = head.substr(beginning);
    // find the end of pow
    var secondArg, untouchedTail;
    if(tail[0] != '{')
    {
        secondArg = tail[0];
        untouchedTail = tail.substr(1);
    }
    else
    {
        counter = 1;
        var len = tail.length;
        var end = len+1;
        for(i = 1; i < len; i++)
        {
            if(tail[i] == '{')
                counter++;
            else if(tail[i] == '}')
                counter--;

            if(counter == 0)
            {
                end = i;
                break;
            }
        }
        secondArg = tail.substr(1,end-1);
        if(end < len-1)
            untouchedTail = tail.substr(end+1);
        else
            untouchedTail = '';
    }

    return untouchedHead
        + 'pow(' + firstArg + ',' + convertLatexPow(secondArg) + ')'
        + convertLatexPow(untouchedTail);
}

alert(convertLatexPow('2^{3^{4^5}}'));
alert(convertLatexPow('\\frac{3}{9}+\\frac{2^{\\sqrt{4^2}}}{6}'));
alert(convertLatexPow('{a + 2 \\cdot (b + c)}^2'));
&#13;
&#13;
&#13;

输入:'2^{3^{4^5}}'
输出:pow(2,pow(3,pow(4,5)))

输入:'\\frac{3}{9}+\\frac{2^{\\sqrt{4^2}}}{6}'
输出:\frac{3}{9}+\frac{pow(2,\sqrt{pow(4,2)})}{6}

输入:'{a + 2 \\cdot (b + c)}^2'
输出:pow({a + 2 \cdot (b + c)},2)

注意:它不解析\sqrt。你必须多做这件事。

随意改进它:)

注意:LaTeX中的^并不意味着 power 。它只是意味着上标。所以2^3变为2 3 (看起来像&#34; 2到3&#34的力量;),但\sum_{i=1}^n只是变得更好格式化。但您可以在^之后直接扩展上述函数以忽略}

注意:正如Lucas Trzesniewski在评论中提到的,2^3^4未被转换&#34;正确&#34;,但它也不是有效的LaTeX表达式。

修改:改进了将'{a + 2 \\cdot (b + c)}^2'转换为正确的功能。

注意:在LaTeX中存在多种编写大括号的方法(例如(\left([\lbrace,..) 。 为了确保此功能适用于所有这些大括号,您应该首先将所有大括号转换为{}。或者使用普通大括号(,但必须编辑该函数以查找(而不是{

注意:此函数的复杂性为O(n⋅k),其中n是输入的长度,k^的数量在输入中。最坏的情况输入将是第一个测试用例2^{3^{4^{...}}}。但在大多数情况下,功能会快得多。关于O(n)的事情。

答案 2 :(得分:0)

您可以迭代地执行此操作:

var foo = "2^(3^(4^5))";
while (/\([^^]+\^[^^]+\)/.test(foo)) {
  foo = foo.replace(/\(([^^]+)\^([^^]+)\)/, "pow($1,$2)");
}
if (/(.+)\^(.+)/.test(foo)) {
  foo = "pow(" + RegExp.$1 + "," + RegExp.$2 + ")";
}
# foo == "pow(2,pow(3,pow(4,5)))"