从字符串求解方程式到C的结果

我想知道是否有人有关于如何做一些听起来很简单但在尝试编程时看起来不像的信息或经验。 这个想法是:给出一个包含等式的字符串,例如:“2 * x = 10”(这很简单,但它可能变得非常复杂,例如sqrt(54)* 35 = x ^ 2;等等在…)和程序将返回x = 5,并可能给出他如何到达那里的日志。

这可行吗? 如果是这样,有没有人有领导? 有关信息,这个网站( http://www.numberempire.com/equationsolver.php )在PHP中做同样的事情,但不是开源的。

谢谢你的帮助 !

这被称为“解析”,虽然计算机科学已经解决了这个问题,但在你彻底理解之前它并不简单。 有一整个计算机科学学科描述了如何解决这个问题。 在C中,您必须定义输入的语法(可能在其中包含优先规则),然后对输入执行词法分析 ,然后解析结果并最终评估您的解析树。

但是,在诸如Ruby之类的语言中,因为你对字符串操作有如此全面的支持,并且因为你有如此巨大的运行时function,你可以用一行代码解决你的问题:

 puts(eval($_)) while gets 

是的,这将涵盖的内容超出了您的要求。

首先,您必须正确定义可以作为输入的方程式。 然后你应该创建一个很好的抽象来表示方程,例如多项式类。 如果要使用更复杂的表达式,请使用树来表示数值表达式。 如果您有将表达式转换为前缀表示法的良好规则,则解析可能非常简单,然后使用堆栈轻松进行评估。 一旦有了算术树或多项式,就可以实现变换来计算变量。

如果方程确实变得复杂,那么C / C ++代码肯定不会很少。

对于线性方程,您必须模拟Linear Algebra Books中描述的方法之一。 这段代码足够小。

您可以尝试将SymPy链接到C(或C ++)代码并使用它来解决方程式。

IIRC,SymPy具有这种function。 另外,应该更容易将输入字符串操作为Python内部的可用方程式,然后将其传递给SymPy进行求解。

问题将分为两个部分:解析方程式,并以符号方式解决它们。 我不会对第一个说太多,因为其他答案已经很好地涵盖了这个主题; 我个人的建议是为前缀表示法中的表达式编写一个简单的递归下降解析器。

第二部分,解析地解决方程,将是棘手的。 一般来说,有一些特殊的方程式,其中存在标准方法来寻找解析解:

  • 线性方程组:任何直接线性求解器。 如果你想明确地显示步骤并且方程/未知数的数量很小,我会推荐一些简单的东西,比如未经加工的高斯消元或克莱默定律。
  • 多项式方程组:在变量替换之后等效,以找到单个多项式的根。 如果这些度<= 4,则存在精确解的公式。 注意:对于3级和4级,这些公式并不令人愉快。
  • 具有有理系数的多项式方程组的有理解:如上所述进行变量替换。 然后使用理性零测试蛮力。
  • 其他类型的方程式:祝你好运。 对于更复杂的[非线性方程组],如果可以求解数值(非解析)解,请查看牛顿方法。

一个修正:这不是线性代数,通常意味着多个方程和未知数的基质。

你的例子当然不复杂。

你需要的是一个简单的表达式语法和解析器。 将等式解析为抽象语法树并遍历树来评估它。

如果您正在编写Java,它可能看起来像这样 。 另一个例子是symja 。 也许这足以让你为C ++提出自己的灵感。

您可能还想查看Mathematica和Wolfram的Alpha。 斯蒂芬沃尔夫勒姆是世界上最好的数学家和计算机科学家之一。 他有很多东西可以重复使用,而不是自己编写。

您必须通过“解决”以及您希望返回的内容来定义您的意思。

有符号解决方案和数值解决方案。 你的意思是哪一个? 两者都同样有效,但它们是不同的。 您将根据您的答案应用不同的技巧。

另一点:有许多“求解”方程的技术在很大程度上取决于方程的类型。 如果你给我一些类似于f(x) = 0我会想到像牛顿方法那样的根寻找算法。 如果你给我一个普通的微分方程,我可以尝试使用Runge-Kutta的替换方法或数值积分。 如果你给我一个偏微分方程,我可以应用有限差分,有限元或边界元素技术。 (不要让我开始研究椭圆形,抛物线和双曲线偏微分方程。)

关键是你的问题非常通用,答案很大程度上取决于你想要做什么。 更多细节可能有所帮助

通常,您必须将表达式解析为一些内部表示。 许多线性代数书建议使用矩阵(或std::vector )来表示系数。 该术语的指数由其在向量中的位置定义。

例如,表达式:

  2 + 3x + 5x^2 

可以表示为数组或std::vector

 std::vector expression; expression[0] = 2; // 2 * x ^ 0 expression[1] = 3; expression[2] = 5; 

编写评估函数变得微不足道,并留给读者练习。

求解多个方程式变得更加复杂。 现有的库和算法。 谷歌搜索应该提出一些好的东西。 🙂

我建议从简单的术语开始并为此构建解析器。 一旦有效,您可以更改解析器以接受函数名称。

如果您正在尝试简化在=两侧都有术语的表达式,请记下手动求解时通常会采取的步骤。 尝试一些不同的方程式来制定一些规则。 现在用C ++实现这些规则。