我想知道是否有一种简单的算法来重新排列简单的符号代数表达式。理想情况下,我希望能够在左侧单独使用一个变量重写任何此类表达式。例如,给定输入:
m = (x + y) / 2
...我希望能够就x
和m
以及y
y
和x
方面提出m
的问题。 x = 2*m - y
y = 2*m - x
,并获取这些:
{{1}}
当然,我们已经在纸上完成了这个算法多年。但我想知道是否有一个名字。这似乎很简单,但如果有人已经记录了各种“陷阱”,那将使生活更轻松。
出于我的目的,我不需要它来处理二次方。
(是的,CAS系统会这样做,是的,我知道我可以将它们用作库。我想在我的应用程序中避免这种依赖。我真的只想知道是否有命名算法接近这个问题。)
答案 0 :(得分:2)
您感兴趣的似乎是维护一个线性方程组,然后,在任何时候,能够根据所有其他变量求解一个变量。如果您将关系编码为矩阵,那么您似乎可以将矩阵缩减为一些不错的形式(例如,减少行梯形形式)以获得变量中的“最简单”依赖关系(对于“最简单”的一些很好的定义)。 “)一旦你有这样的数据,你应该能够通过查看有问题的变量具有非零条目的某一行来读取所有依赖关系,然后对其进行标准化以使变量具有系数1。
注意 - 通常,您不会总是为每个变量获得唯一的解决方案。例如,给定平凡的方程式
x = y
x = z
然后求解z可以产生“z = x”或“z = y”,这取决于你想要多少简化。或者,在像
这样的设置中x = 2y + 3w
x = 9z
返回x的值可以回退表达式,或者它们的总和超过两个,或者一大堆其他技术上都是真实但不一定有用的东西。我不确定你是如何处理的,但根据方程式的形式,你可能会找到一种方法来处理它。
答案 1 :(得分:2)
你想要的是方程求解算法。但我敢打赌,这是一个很大的话题。一般情况下,可能有:
sin(x) + 10 = z
,求解x我们反转sin(),即arcsin()。 (并非所有功能都可以是可逆的!)sin(x)+x=y
,求解x。答案很难 - 你最好的选择是获取某些CAS的源代码,例如你可以查看用LISP编写的MAXIMA CAS源代码。并找到负责方程求解的代码。
简单回答 - 如果您需要的只是求解线性的方程式,并且仅由基本运算符+ - * /组成。然后你就知道了答案 - 使用旧的好纸方法 - 想想我们在纸上使用的规则,然后重新编写这些规则作为操纵方程式字符串的符号算法。
祝你好运!答案 2 :(得分:0)
有各种简单的方法可以修改初始方程,以正确的顺序执行正确的修改将导致正确的解决方案。那么如何将其视为搜索甚至寻路问题呢?
答案 3 :(得分:0)
将您的表达式转换为反向波兰表示法的数据结构(树)。你的树由节点组成,每个节点都有一个操作,一个左边和一个右边。 left 和 right 中的每一个都可以是一个符号(例如:“x”)或另一个节点。例如:
(x + (a + b))
会变成:
(+ x (+ a b))
或在 JSON 中:
["+", "x", ["+", "a", "b"]]
您的原始表达式 m = (x + y) / 2
将如下所示:
m = ["/", ["+", "x", "y"], "2"]
您想要的表达式之一(求解 x)如下所示:
x = ["-", ["*", "m", "2"], "y"]
你能看到表达式树被颠倒了,每个运算符都被颠倒了吗? “-”是“+”的反面,现在包裹“*”,这是“/”的反面。该:
["+", "x", "y"]
变成:
["-", (something), "y"]
Where (something) 是外部表达式的递归反转。尝试解释该过程:a) 递归地降低表达式树,直到找到包含要求解的符号的节点,b) 创建一个包含此节点操作逆向的新节点,c) 替换要求解的符号用反向的外部表达式求解,在向外返回时递归地执行此操作。