从字符串解方程得到 C 的结果
我想知道是否有人有关于如何做一些听起来很简单但在尝试编程时看起来并不像的事情的信息或经验。 这个想法是:给出一个包含方程的字符串,例如:“2*x = 10”(这很简单,但它可能会变得非常复杂,例如 sqrt(54)*35=x^2; 等等on....),程序将返回 x = 5,并可能给出他如何到达那里的日志。
这可行吗?如果是这样,有人有线索吗?有关信息,请访问此网站(http://www.numberempire.com/equationsolver.php )它在 PHP 中做同样的事情,但不是开源的。
感谢您的帮助!
I would like to know if anyone has info or experience on how to do something which sounds simple but doesn't look like it when trying to program it.
The idea is : give a string containing an equation, such as : "2*x = 10" for example (this is simple, but it could get very complex, such as sqrt(54)*35=x^2; and so on....) and the program would return x = 5 and possibly give a log of how he got there.
Is this doable ? If so, does anyone have a lead ? For info there is this site (http://www.numberempire.com/equationsolver.php) which does the same thing in PHP, but isn't open source.
Thanks for any help !
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
这就是所谓的“解析”,尽管计算机科学已经解决了这个问题,但在你彻底理解它之前,它一点也不简单。有一个完整的计算机科学学科描述了如何解决这个问题。在 C 中,您必须定义输入的语法(可能包含优先级规则),然后对输入执行词法分析,然后解析结果,最后评估您的解析树。
然而,在像 Ruby 这样的语言中,因为你对字符串操作有如此彻底的支持,并且因为你有如此强大的运行时能力,所以你可以用一行代码解决你的问题,如下所示:
是的,这将涵盖比你要求的更多的内容。
This is called "parsing", and although computer science has already solved this problem it isn't simple at all until you understand it thoroughly. There's an entire computer-science discipline that describes how to solve this problem. In C you must define the grammar of your input (possibly with precedence rules in it), then perform lexical analysis on your input, then parse the result and finally evaluate your parse tree.
In languages such as Ruby, however, because you have such thorough support for string manipulation and because you have such tremendous runtime power you can solve your problem with a single line of code like so:
Yes, that will cover more than what you ask for.
首先,您必须正确定义可以作为输入的方程类型。然后你应该创建一个好的抽象来表示方程,例如多项式类。当您想使用更复杂的表达式时,请使用数值表达式树。如果您有良好的规则将表达式转换为前缀表示法,则解析可能会非常容易,然后使用堆栈进行评估很容易。一旦有了算术树或多项式,您就可以实现转换来计算变量。
Firstly you have to properly define what kinds of equations you can have as an input. Then you should create a good abstraction to represent the equation, e.g. a polynomial class. When you want to use more complex expression, go for a tree for numerical expressions. Parsing can be quite easy if you have good rules to convert the expression into prefix notation, then evaluation is easy using stacks. Once you have artithmetic trees or polynomials, you can implement transformations to compute the variable(s).
如果方程确实变得复杂,那肯定不会是几行 C/C++ 代码。
对于线性方程,您必须模拟线性代数书籍中描述的方法之一。其代码足够小。
If equations do get complex, It won't surely be few lines of C/C++ code.
For linear equations, you would have to simulate one of the methods described in Linear Algebra Books. The code of that is small enough.
您可以尝试在 SymPy 中链接到您的 C(或 C++)代码并使用它来求解方程。
IIRC、SymPy 都有这种功能。另外,在 Python 中将输入字符串操作为可用方程,然后将其传递给 SymPy 进行求解应该更容易。
You could try linking in SymPy to your C (or C++) code and using it to solve your equations.
IIRC, SymPy has that kind of functionality. Plus, it should be easier to manipulate the input string to a usable equation inside of Python and then pass it off to SymPy for solving.
您的问题将分为两个部分:解析方程并以符号方式求解它们。关于第一个我不会说太多,因为其他答案已经很好地涵盖了这个主题;我个人的建议是为前缀表示法的表达式编写一个简单的递归下降解析器。
第二部分,解析解方程,将会很棘手。一般来说,有一些特殊类型的方程,可以使用标准方法来找到解析解:
There's going to be two parts to your problem: parsing the equation(s), and solving them symbolically. I'm not going to say much about the first, since other answers have already covered that topic well; my personal recommendation would be to write a simple recursive descent parser for expressions in prefix notation.
The second part, solving equations analytically, is going to be tricky. Generally speaking there are special classes of equations for which standard methods exist to find an analytic solution:
一项更正:这不是线性代数,线性代数通常意味着多个方程和未知数的矩阵。
你的例子当然并不复杂。
您需要的是一个简单的表达式语法和解析器。将方程解析为抽象语法树,并遍历树对其进行评估。
如果您正在编写 Java,它可能看起来像 这个。另一个示例是 symja。也许这会给您带来足够的灵感,让您想出自己的 C++ 语言。
您可能还想研究 Mathematica 和 Wolfram 的 Alpha。斯蒂芬·沃尔夫勒姆 (Stephen Wolfram) 是世界上最好的数学家和计算机科学家之一。他有很多东西你可以重用,而不是自己编写。
您必须定义“解决”的含义以及您期望返回的结果。
有符号解和数值解。你指的是哪一个?两者同样有效,但又有所不同。您将根据您的答案应用不同的技术。
另一点:有许多“求解”方程的技术在很大程度上取决于方程的类型。如果你给我类似
f(x) = 0
的东西,我会想到像牛顿法这样的求根算法。如果你给我一个常微分方程,我可能会尝试使用龙格-库塔的替代方法或数值积分。如果你给我一个偏微分方程,我可以应用有限差分、有限元或边界元技术。 (不要让我开始讨论椭圆、抛物线和双曲偏微分方程。)重点是你的问题非常笼统,答案很大程度上取决于你想要做什么。更多细节可能会有所帮助。
One correction: this isn't linear algebra, which usually means matricies of multiple equations and unknowns.
Your example certainly isn't complex.
What you need is a simple expression grammar and parser. Parse the equation into an abstract syntax tree and walk the tree to evaluate it.
If you were writing Java it might look like this. Another example is symja. Perhaps it'll be enough inspiration for you to come up with your own for C++.
You might also want to look into Mathematica and Wolfram's Alpha. Stephen Wolfram is one of the world's best mathematicians and computer scientists. He's got a lot of stuff that you could reuse to good advantage rather than writing it yourself.
You'll have to define what you mean by "solve" and what you expect to have returned.
There are symbolic solutions and numerical solutions. Which one do you mean? Both are equally valid, but they're different. You'll apply different techniques depending on your answer.
Another point: there are many techniques for "solving" equations that depend a great deal on the type of equation. If you give me something like
f(x) = 0
I think of root finding algorithms like Newton's method. If you give me an ordinary differential equation I might try a substitution method or numerical integration using Runge-Kutta. If you give me a partial differential equation I can apply finite difference, finite element, or boundary element techniques. (Don't get me started on elliptical, parabolic, and hyperbolic PDEs.)The point is that your question is very generic, and the answer depends a great deal on what you're trying to do. More detail might help.
一般来说,您必须将表达式解析为某种内部表示。许多线性代数书籍建议使用矩阵(或 std::vector)来表示系数。该项的指数由其在向量中的位置定义。
例如,表达式:
可以表示为数组或 std::vector:
编写求值函数变得微不足道,可以作为读者的练习。
求解多个方程变得更加复杂。有现有的库和算法用于此目的。谷歌搜索应该能找到一些好东西。 :-)
我建议从简单的术语开始,并为此构建一个解析器。一旦成功,您就可以更改解析器以接受函数名称。
如果您试图简化
=
两边都有项的表达式,只需写下您在手动求解时通常采取的步骤即可。尝试一些不同的方程来得出一些规则。现在用 C++ 实现这些规则。In general, you will have to parse the expression into some internal representation. Many linear algebra books suggest using matrices (or
std::vector
) to represent the coefficients. The exponent of the term is defined by its position in the vector.So for example, the expression:
Can be represented as an array or
std::vector
:Writing an evaluation function becomes trivial, and left as an exercise for the reader.
Solving multiple equations becomes more complex. There are existing libraries and algorithms for this. A Google search should come up with something good. :-)
I suggest starting out with simple terms and building a parser for that. Once that works, you can change the parser to accept function names as well.
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++.