3

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

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

谢谢你的帮助 !

4

7 回答 7

3

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

然而,在诸如 Ruby 之类的语言中,因为您对字符串操作有如此彻底的支持,并且因为您拥有如此强大的运行时能力,所以您可以用一行代码解决您的问题,如下所示:

puts(eval($_)) while gets

是的,这将比您要求的更多。

于 2010-05-16T18:44:41.557 回答
2

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

于 2010-05-16T18:39:21.047 回答
1

如果方程式确实变得复杂,那肯定不会是几行 C/C++ 代码。

对于线性方程,您必须模拟线性代数书籍中描述的方法之一。它的代码足够小。

于 2010-05-16T18:36:26.230 回答
1

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

你的例子当然并不复杂。

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

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

您可能还想研究 Mathematica 和 Wolfram 的 Alpha。Stephen Wolfram 是世界上最优秀的数学家和计算机科学家之一。他有很多东西可以让你充分利用而不是自己写。

您必须定义“解决”的含义以及您期望返回的内容。

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

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

关键是您的问题非常笼统,答案在很大程度上取决于您要做什么。更多细节可能会有所帮助。

于 2010-05-16T18:37:10.107 回答
1

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

IIRC,SymPy 具有这种功能。此外,在 Python 中将输入字符串操作为可用方程,然后将其传递给 SymPy 进行求解应该更容易。

于 2010-05-16T18:44:52.710 回答
1

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

第二部分,解析解方程,会很棘手。一般而言,有一些特殊类别的方程可以使用标准方法来找到解析解:

  • 线性方程组:任何直接线性求解器。如果您想明确显示这些步骤并且方程/未知数的数量很少,我建议您使用一些简单的方法,例如无主高斯消元法或克莱默法则。
  • 多项式方程组:在变量替换后,等效于找到单个多项式的根。如果这些度数 <= 4,则有精确解的公式。注意:对于 3 级和 4 级,这些公式并不令人愉快。
  • 具有有理系数的多项式方程组的有理解:如上所述进行变量替换。然后使用理性零测试蛮力。
  • 其他类型的方程式:祝你好运。对于更复杂的[系统]非线性方程,如果您可以解决数值(非解析)解决方案,请查看牛顿法。
于 2010-05-16T19:04:33.723 回答
1

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

例如,表达式:

 2 + 3x + 5x^2

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

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

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

求解多个方程变得更加复杂。有用于此的现有库和算法。谷歌搜索应该会找到一些好的东西。:-)

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

If you are trying to simplify an expression that has terms on both sides of the =, just write down the steps you would normally take when solving by hand. Try some different equations to get some rules down. Now implement these rules in C++.

于 2010-05-17T16:46:34.657 回答