【问题标题】:Single-Variable Symbolic Differentiation from Expression Trees表达式树的单变量符号微分
【发布时间】:2021-04-03 09:09:47
【问题描述】:

我正在尝试找到以符号方式计算 Javascript 中类型化数学函数的导数的最佳方法/算法。每个方程只有一个变量。 我从一个类型化的表达式开始,然后使用 Dijkstra 的 shunting-yard algorithm 将中缀方程转换为后缀方程,然后将其转换为 RPN(反向波兰表示法)。我的下一个想法是使用它来创建一个表达式树,最终看起来像这样:

Equation: 25x^2 + 61x + 3

RPN: 25 x 2 ^ * 61 x * + 3 +

表达式树:

我查看了“已解决”的表达式树应该是什么样子,以了解需要做什么:

Derivative (without simplification): x^(2-1)*2*25+61

我在想我可以使用 postorder traversal 递归地应用微分规则(乘积、商、总和、差等),并根据运算符替换“节点”。

但是,在查看导数的表达式树之后,我意识到我不能轻易地将诸如乘积规则之类的东西应用于仍然有子节点的节点(即this

所以我的主要问题是:是否有任何已知的类似于 shutting-yard 的算法可以有效地以编程方式计算符号导数?

【问题讨论】:

标签: javascript symbolic-math derivative


【解决方案1】:

Shunting Yard 算法更多的是解析而不是转换,因此恕我直言,最好遍历生成的表达式树,在单独的树中构建导数表达式。对于简单的表达式,就地替换似乎是解决方案,但随着数学表达式变得更加复杂,微分规则(参见https://en.wikipedia.org/wiki/Differentiation_rules)将使树操作变得复杂,尤其是当算法深入到子节点时进一步区分。比如……

  • 乘积规则是 f(x) g(x) = f'(x) g(x) + f(x) g'(x)

...因此,区分以下...

  • x * ln( x )

...导致...

  • ( x )' * ln( x ) + x * ( ln( x ) )'
  • 1 * ln( x ) + x * 1/x

我想您还会发现,一旦创建了导数,就需要对表达式进行一些代数清理。按照示例,该算法将需要第二遍遍历导数树并根据代数规则简化表达式,例如...

  • 1 * n = n
  • n * 1 / n = 1

...所以最终的结果是...

  • ln( x ) + 1

https://www.derivative-calculator.net/ 实际上有一个很好的资源,它是您在代码中寻求执行的实现,可能值得尝试以了解所涉及的逻辑。此外,Calculate string value in javascript, not using eval 上还有一个出色的 Shutting Yard 算法实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-21
    相关资源
    最近更新 更多