在JavaScript中评估Latex数学公式

15
我正在制作一个基于HTML的计算器,并且希望在Javascript中渲染表达式并进行评估。我希望表达式以LaTeX编写,并且可以交互式地编辑已呈现的表达式,但其他语言也可以。之前尝试过使用MathQuill进行交互渲染,然后使用MathJS进行评估。这在某种程度上可以工作,但由于两个软件包的设计目标不同(MathQuill用于呈现LaTeX,而MathJS具有自定义的数学语法),因此它的可靠性不够高(例如,如果用户输入\frac{5}{17*x} 并假定它是正确的语法,然后进行评估并从MathJS获得错误)。
目前,我看到三种继续进行的方法:
  • 继续使用我现有的内容(或者可能切换到更好的MathJax)。
  • 查找可以同时进行渲染和评估的工具(无论是使用LaTeX还是其他语言)。
  • 查找具有相近(如果不是相同)语法的渲染和评估两个工具。
  • 按照这里建议的编写自己的渲染和评估工具。我不想这样做,因为这似乎有点繁琐,并且我不想重新发明轮子。
哪种方法最好?更新 1: 在查看了altJS提供的替代语言列表后,我认为我可以使用Python、Ruby或Basic作为用户输入语言。如果这样做,将会为它带来很多渲染的可能性(从技术上讲,这并不是“渲染”,但是想象一下有多少个语法高亮器存在)。但是,我不希望用户能够访问这些语言的更高级元素,因为这会给我的用户增加困惑,并且也可能不安全(比如使用eval)。我只希望用户能够使用数学运算、变量(仅限我指定的那些,以及用户自定义的),以及函数(仅限我指定的那些,以及用户自定义的)。有没有办法限制可以使用的子集语言? 更新 2: 我在altJS页面上再次搜索发现,几乎所有语言都是设计用于将语言XYZ编译成JavaScript,然后在页面上运行JavaScript,而不是在页面上运行语言XYZ。在页面上运行,我还没有详细研究每一个语言,但是其中大部分似乎都是这样。其他一些语言,例如Brython,则似乎被设计为在浏览器中运行语言XYZ,但作为JavaScript的替代/补充而不是用户输入语言。有没有一些解决方法,以便我可以将这些方法用作输入? 更新 3: 感谢@SpaceDog提供的信息,并指出我在说明用户应该能够实现什么方面还不够具体。因此,这里是我希望实现的功能:
  1. 基本运算(加、减、乘、除/分数、指数、开方、模数)
  2. 函数(三角函数、对数等)
  3. 常量(e、pi等)
  4. 变量(赋值、重新赋值和使用它们)
  5. 用户定义的函数

LaTeXCalc似乎符合这些要求,除了最后一个。此外,它似乎不是用Javascript编写的。

这让我想到另一个想法:使用类似MathJax的东西来呈现,然后使用Wolfram Alpha API来处理计算。它的好处是它会有更高级的选项,既适用于输入又适用于输出。然而,应用程序将变得无用(如果计算器实际上只是一个克隆,为什么不直接使用wolframalpha.com?),它需要花钱,并且该应用程序无法脱机工作(它是一个使用HTML/CSS/JS编写的桌面应用程序)。对此有何想法?


也许我对于这个类似问题的回答可以帮到你。 - Jeff Hernandez
1个回答

8
看起来你想要做两件不同的事情,一个是漂亮地展示方程式,另一个是计算它。所以你需要一个既能展示又能计算的工具。Latex 更注重于展示而非计算,尽管对于其中的一部分可以进行计算(参见此答案:Is there a calculator with LaTeX-syntax?)。
很多因素取决于你想让计算器变得有多复杂——你想允许哪些操作。如果你只使用了小的子集(听起来是这样),那么手动编写转换器将会相当容易。我建议你研究一下 MathML,它具有呈现和语义标记,并且有许多可用的工具。但是,它可能不是用户最容易理解的。如果用户熟悉 LaTeX,并且所包含的符号子集较小,则将 LaTeX 解析为可直接计算的格式将非常容易。
我认为你需要明确定义用户可以访问的内容,以便任何人都可以提供更好的示例来说明什么是“最佳”的。
好的,你离编写完整的编程语言已经很接近了(只需要条件和循环 - 或标签)。因此,重新发明轮子似乎不是一个好主意。在这种情况下,我肯定认为你不想使用LaTeX作为输入语言,最好选择一些更熟悉你的用户的东西。
以下是如果我要做这件事情并开始时的建议,这并不是一个明确的答案,我会在开始之前进行更多的研究,以确保我不会重复努力。
我会构建一个解析器,它可以接受JavaScript的子集,这个解析器将会有两个功能(或者说会有两个解析器),一个是将代码转换为LaTeX或MathML,第二个是评估/执行代码。
在离线状态下,在C中完成这个任务,我会使用Lex和Yacc(或Flex和Bison等),通过快速搜索得知有一个JavaScript等效工具:Jison。那将为您提供语言解析器的骨架,您可以对其进行修改。

或者你可以尝试使用现有的JS解析器,这可能会有所帮助。请参考此答案: JavaScript parser in JavaScript

一旦你有了解析骨架,一开始可以保持简单 -- 将其翻译成可显示的语言应该相当容易,并且为了评估,你可以冒险使用eval -- 因为解析器已经确保输入只使用你允许的内容。然而,我建议在生产版本中不要这样做(测试时可以),并且将令牌映射到内部函数并不需要太多额外的工作。

之后,你可能想要改进显示输出,也许你想要尝试简化输入或重新排序以使其更有意义。这将需要从你的解析器中获取内部表示,并对其进行一些巧妙的处理。但首先要让第一步起作用。

您希望此程序可以离线工作,因此我提出的使用服务器托管其他示例程序的想法行不通(在那种情况下,使用Wolfram Alpha或Google是一个好选择--但正如您所说,那么这个程序有什么意义呢)。但是,您也可以考虑是否可以从不同的基本语言开始编写此程序,尽管我猜测您想要HTML/JS/CSS的可移植性。

您提供的其他链接都是其他可能的想法,我只是认为,与依赖于第三方代码的每个应用程序相比,拥有自己的解析器将获得更多的益处。通过自己的解析器,您可以随时轻松添加功能或语言特性。

最后一个想法是,您不一定限制输入为JavaScript。如果您认为您的用户能够应对逆波兰表示法,那么手动编写解析器很容易--但您必须对其进行一些格式化以使其输出漂亮。


1
MathJax是JavaScript,并且可以与MathML一起使用,我也会直接在JS中编写解析。 - SpaceDog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接