<tfoot id='CGr6m'></tfoot>
  1. <legend id='CGr6m'><style id='CGr6m'><dir id='CGr6m'><q id='CGr6m'></q></dir></style></legend>

    <i id='CGr6m'><tr id='CGr6m'><dt id='CGr6m'><q id='CGr6m'><span id='CGr6m'><b id='CGr6m'><form id='CGr6m'><ins id='CGr6m'></ins><ul id='CGr6m'></ul><sub id='CGr6m'></sub></form><legend id='CGr6m'></legend><bdo id='CGr6m'><pre id='CGr6m'><center id='CGr6m'></center></pre></bdo></b><th id='CGr6m'></th></span></q></dt></tr></i><div id='CGr6m'><tfoot id='CGr6m'></tfoot><dl id='CGr6m'><fieldset id='CGr6m'></fieldset></dl></div>
      <bdo id='CGr6m'></bdo><ul id='CGr6m'></ul>

      <small id='CGr6m'></small><noframes id='CGr6m'>

    1. 将 LaTeX 转换为动态 Javascript 函数

      时间:2024-04-18
      <i id='XTEvK'><tr id='XTEvK'><dt id='XTEvK'><q id='XTEvK'><span id='XTEvK'><b id='XTEvK'><form id='XTEvK'><ins id='XTEvK'></ins><ul id='XTEvK'></ul><sub id='XTEvK'></sub></form><legend id='XTEvK'></legend><bdo id='XTEvK'><pre id='XTEvK'><center id='XTEvK'></center></pre></bdo></b><th id='XTEvK'></th></span></q></dt></tr></i><div id='XTEvK'><tfoot id='XTEvK'></tfoot><dl id='XTEvK'><fieldset id='XTEvK'></fieldset></dl></div>

        <bdo id='XTEvK'></bdo><ul id='XTEvK'></ul>
            <tbody id='XTEvK'></tbody>
          <legend id='XTEvK'><style id='XTEvK'><dir id='XTEvK'><q id='XTEvK'></q></dir></style></legend>

          <tfoot id='XTEvK'></tfoot>

            <small id='XTEvK'></small><noframes id='XTEvK'>

                本文介绍了将 LaTeX 转换为动态 Javascript 函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                问题描述

                我有一个方程的用户输入 - 这个输入使用我没有编码的单独 API 生成 LaTeX 代码(即,Mathquill,没关系).

                I have a user input for an equation - this input generates LaTeX code using a separate API which I did not code (namely, Mathquill, not that it matters).

                我的问题最好用一个例子来说明:假设从用户输入生成的 LaTeX 代码是这样的:

                My problem is best illustrated by an example: suppose the LaTeX code generated from the user input was this:

                x^2+3x-10sinleft(2x
                ight) 
                

                我如何将它(当然是在运行中)转换成一个硬编码的 JavaScript 函数,如下所示:

                How would I convert this (on the fly of course) into a JavaScript function which, hard-coded, would look like this:

                function(x) {
                  return Math.pow(x, 2) + 3 * x - 10 * Math.sin(2 * x);
                }
                

                是否有任何 API,或者我是否正在考虑编写一些可以解释 LaTeX 符号并以某种方式生成函数的东西?还是什么?

                Are there any APIs or am I looking at writing something which will interpret the LaTeX symbols and make a function, somehow? Or what?

                推荐答案

                我已经编写了一个(绝不是通用的)解决方案,主要基于 George 的代码.

                I have written a (by no means general purpose) solution, heavily based on George's code.

                这里是:

                var CALC_CONST = {
                  // define your constants
                  e: Math.E,
                  pi: Math.PI
                };
                
                var CALC_NUMARGS = [
                  [/^(^|*|/|+|-)$/, 2],
                  [/^(floor|ceil|(sin|cos|tan|sec|csc|cot)h?)$/, 1]
                ];
                
                var Calc = function(expr, infix) {
                  this.valid = true;
                  this.expr = expr;
                
                  if (!infix) {
                    // by default treat expr as raw latex
                    this.expr = this.latexToInfix(expr);
                  }
                
                  var OpPrecedence = function(op) {
                    if (typeof op == "undefined") return 0;
                
                    return op.match(/^(floor|ceil|(sin|cos|tan|sec|csc|cot)h?)$/) ? 10
                
                         : (op === "^") ? 9
                         : (op === "*" || op === "/") ? 8
                         : (op === "+" || op === "-") ? 7
                
                         : 0;
                  }
                
                  var OpAssociativity = function(op) {
                    return op.match(/^(floor|ceil|(sin|cos|tan|sec|csc|cot)h?)$/) ? "R" : "L";
                  }
                
                  var numArgs = function(op) {
                    for (var i = 0; i < CALC_NUMARGS.length; i++) {
                      if (CALC_NUMARGS[i][0].test(op)) return CALC_NUMARGS[i][1];
                    }
                    return false;
                  }
                
                  this.rpn_expr = [];
                  var rpn_expr = this.rpn_expr;
                
                  this.expr = this.expr.replace(/s+/g, "");
                
                  // This nice long regex matches any valid token in a user
                  // supplied expression (e.g. an operator, a constant or
                  // a variable)
                  var in_tokens = this.expr.match(/(^|*|/|+|-|(|)|[a-zA-Z0-9.]+)/gi);
                  var op_stack = [];
                
                  in_tokens.forEach(function(token) {
                    if (/^[a-zA-Z]$/.test(token)) {
                      if (CALC_CONST.hasOwnProperty(token)) {
                        // Constant. Pushes a value onto the stack.
                        rpn_expr.push(["num", CALC_CONST[token]]);
                      }
                      else {
                        // Variables (i.e. x as in f(x))
                        rpn_expr.push(["var", token]);
                      }
                    }
                    else {
                      var numVal = parseFloat(token);
                      if (!isNaN(numVal)) {
                        // Number - push onto the stack
                        rpn_expr.push(["num", numVal]);
                      }
                      else if (token === ")") {
                        // Pop tokens off the op_stack onto the rpn_expr until we reach the matching (
                        while (op_stack[op_stack.length - 1] !== "(") {
                          rpn_expr.push([numArgs(op_stack[op_stack.length - 1]), op_stack.pop()]);
                          if (op_stack.length === 0) {
                            this.valid = false;
                            return;
                          }
                        }
                
                        // remove the (
                        op_stack.pop();
                      }
                      else if (token === "(") {
                        op_stack.push(token);
                      }
                      else {
                        // Operator
                        var tokPrec = OpPrecedence(token),
                           headPrec = OpPrecedence(op_stack[op_stack.length - 1]);
                
                        while ((OpAssociativity(token) === "L" && tokPrec <= headPrec) ||
                          (OpAssociativity(token) === "R" && tokPrec < headPrec)) {
                
                          rpn_expr.push([numArgs(op_stack[op_stack.length - 1]), op_stack.pop()]);
                          if (op_stack.length === 0) break;
                
                          headPrec = OpPrecedence(op_stack[op_stack.length - 1]);
                        }
                
                        op_stack.push(token);
                      }
                    }
                  });
                
                  // Push all remaining operators onto the final expression
                  while (op_stack.length > 0) {
                    var popped = op_stack.pop();
                    if (popped === ")") {
                      this.valid = false;
                      break;
                    }
                    rpn_expr.push([numArgs(popped), popped]);
                  }
                }
                
                /**
                 * returns the result of evaluating the current expression
                 */
                Calc.prototype.eval = function(x) {
                  var stack = [], rpn_expr = this.rpn_expr;
                
                  rpn_expr.forEach(function(token) {
                    if (typeof token[0] == "string") {
                      switch (token[0]) {
                        case "var":
                          // Variable, i.e. x as in f(x); push value onto stack
                          //if (token[1] != "x") return false;
                          stack.push(x);
                          break;
                
                        case "num":
                          // Number; push value onto stack
                          stack.push(token[1]);
                          break;
                      }
                    }
                    else {
                      // Operator
                      var numArgs = token[0];
                      var args = [];
                      do {
                        args.unshift(stack.pop());
                      } while (args.length < numArgs);
                
                      switch (token[1]) {
                        /* BASIC ARITHMETIC OPERATORS */
                        case "*":
                          stack.push(args[0] * args[1]);
                          break;
                        case "/":
                          stack.push(args[0] / args[1]);
                          break;
                        case "+":
                          stack.push(args[0] + args[1]);
                          break;
                        case "-":
                          stack.push(args[0] - args[1]);
                          break;
                
                        // exponents
                        case "^":
                          stack.push(Math.pow(args[0], args[1]));
                          break;
                
                        /* TRIG FUNCTIONS */
                        case "sin":
                          stack.push(Math.sin(args[0]));
                          break;
                        case "cos":
                          stack.push(Math.cos(args[0]));
                          break;
                        case "tan":
                          stack.push(Math.tan(args[0]));
                          break;
                        case "sec":
                          stack.push(1 / Math.cos(args[0]));
                          break;
                        case "csc":
                          stack.push(1 / Math.sin(args[0]));
                          break;
                        case "cot":
                          stack.push(1 / Math.tan(args[0]));
                          break;
                        case "sinh":
                          stack.push(.5 * (Math.pow(Math.E, args[0]) - Math.pow(Math.E, -args[0])));
                          break;
                        case "cosh":
                          stack.push(.5 * (Math.pow(Math.E, args[0]) + Math.pow(Math.E, -args[0])));
                          break;
                        case "tanh":
                          stack.push((Math.pow(Math.E, 2*args[0]) - 1) / (Math.pow(Math.E, 2*args[0]) + 1));
                          break;
                        case "sech":
                          stack.push(2 / (Math.pow(Math.E, args[0]) + Math.pow(Math.E, -args[0])));
                          break;
                        case "csch":
                          stack.push(2 / (Math.pow(Math.E, args[0]) - Math.pow(Math.E, -args[0])));
                          break;
                        case "coth":
                          stack.push((Math.pow(Math.E, 2*args[0]) + 1) / (Math.pow(Math.E, 2*args[0]) - 1));
                          break;
                
                
                        case "floor":
                          stack.push(Math.floor(args[0]));
                          break;
                        case "ceil":
                          stack.push(Math.ceil(args[0]));
                          break;
                
                        default:
                          // unknown operator; error out
                          return false;
                      }
                    }
                  });
                
                  return stack.pop();
                };
                
                Calc.prototype.latexToInfix = function(latex) {
                  /**
                    * function: converts latex notation to infix notation (human-readable, to be converted
                    * again to prefix in order to be processed
                    *
                    * Supported functions / operators / notation:
                    * parentheses, exponents, adding, subtracting, multipling, dividing, fractions
                    * trigonometric (including hyperbolic) functions, floor, ceil
                    */
                
                  var infix = latex;
                
                  infix = infix
                    .replace(/\frac{([^}]+)}{([^}]+)}/g, "($1)/($2)") // fractions
                    .replace(/\left(/g, "(") // open parenthesis
                    .replace(/\right)/g, ")") // close parenthesis
                    .replace(/[^(](floor|ceil|(sin|cos|tan|sec|csc|cot)h?)(([^()]+))[^)]/g, "($&)") // functions
                    .replace(/([^(floor|ceil|(sin|cos|tan|sec|csc|cot)h?|+|-|*|/)])(/g, "$1*(")
                    .replace(/)([w])/g, ")*$1")
                    .replace(/([0-9])([A-Za-z])/g, "$1*$2")
                  ;
                
                  return infix;
                };
                

                使用示例:

                var latex = "e^x+\frac{2}{3}x-4sin\left(x\right)";
                
                var calc = new Calc(latex);
                
                var test = calc.eval(3.5); // 36.85191820278412
                

                这篇关于将 LaTeX 转换为动态 Javascript 函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                上一篇:如何最好地编写针对 HTML 和 PDF 的文档? 下一篇:在 HTML 文件中包含 LaTeX 公式?

                相关文章

                  <bdo id='GXSM7'></bdo><ul id='GXSM7'></ul>

                1. <legend id='GXSM7'><style id='GXSM7'><dir id='GXSM7'><q id='GXSM7'></q></dir></style></legend>
                  1. <small id='GXSM7'></small><noframes id='GXSM7'>

                  2. <tfoot id='GXSM7'></tfoot>

                    <i id='GXSM7'><tr id='GXSM7'><dt id='GXSM7'><q id='GXSM7'><span id='GXSM7'><b id='GXSM7'><form id='GXSM7'><ins id='GXSM7'></ins><ul id='GXSM7'></ul><sub id='GXSM7'></sub></form><legend id='GXSM7'></legend><bdo id='GXSM7'><pre id='GXSM7'><center id='GXSM7'></center></pre></bdo></b><th id='GXSM7'></th></span></q></dt></tr></i><div id='GXSM7'><tfoot id='GXSM7'></tfoot><dl id='GXSM7'><fieldset id='GXSM7'></fieldset></dl></div>