简体   繁体   English

Java:求解符号代数方程

[英]Java: solving symbolic algebraic equations

I'm having trouble adding this functionality to my calculator app.我无法将此功能添加到我的计算器应用程序中。 Here's what I had in mind:这是我的想法:

I want to solve: 2x = 5 + 4x .我想解决: 2x = 5 + 4x

To solve this is no problem if I would use an external token library to parse the equation, but since my entire program is built around a shunting yard parser (EXP4J), it complicates things.为了解决这个问题,如果我使用外部令牌库来解析方程,那是没有问题的,但是由于我的整个程序是围绕一个分流码解析器 (EXP4J) 构建的,所以它使事情变得复杂。 You might say that I could just use the token parser for specific cases, but when you consider that I have FUNCTIONS using EXP4J, it becomes really tangled.你可能会说我可以只在特定情况下使用令牌解析器,但是当你考虑到我有使用 EXP4J 的 FUNCTIONS 时,它变得非常纠结。

So, while I could make it work for 2x = 5 + 4x by simply alternating to a token parser for this specific case, calculations that use EXP4J, like:因此,虽然我可以通过简单地在这种特定情况下交替使用令牌解析器来使其适用于2x = 5 + 4x ,但使用 EXP4J 的计算,例如:

2x = 5*exp4jfunc(x + 5,x) + cos(x) are completely beyond me. 2x = 5*exp4jfunc(x + 5,x) + cos(x)完全超出我的范围。

Does anyone have any idea on how to get around this?有没有人知道如何解决这个问题? I don't even know how my CASIO tackles this, as it freezes on solve-for-x equations like x = 9^x ...我什至不知道我的卡西欧是如何解决这个问题的,因为它冻结在求解x = 9^x这样的 x 方程上......

With the symja library you can solve your problem like this:使用symja 库,您可以像这样解决您的问题:

package org.matheclipse.core.examples;

import org.matheclipse.core.eval.ExprEvaluator;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.parser.client.SyntaxError;
import org.matheclipse.parser.client.math.MathException;

public class Solve2Example {

    public static void main(String[] args) {
        try {
            ExprEvaluator util = new ExprEvaluator();
            IExpr result = util.evaluate("Solve(2*x==5 + 4*x,x)");
            // print: {{x->-5/2}}
            System.out.println(result.toString());

            result = util.evaluate("Roots(2*x==5+4*x, x)");
            // print: x==-5/2
            System.out.println(result.toString());
        } catch (SyntaxError e) {
            // catch Symja parser errors here
            System.out.println(e.getMessage());
        } catch (MathException me) {
            // catch Symja math errors here
            System.out.println(me.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

You can look into the implementation of the Roots() function how the parsed AST is transformed to solve the equation.您可以查看Roots() 函数的实现,它是如何转换解析后的 AST 来求解方程的。

I am not really familiar with exp4j... Given that the Expression class doesn't seem to provide much access to the parsed structure, a symbolic approach seems not really feasible with exp4j.我对 exp4j 不是很熟悉……鉴于Expression类似乎没有提供对解析结构的太多访问,因此符号方法对于 exp4j 似乎并不真正可行。

One thing you could try with exp4j instead:您可以尝试使用 exp4j 代替:

  • Split the equation at = into left and right在拆分公式=leftright

  • Build a new equation that is the difference of both sides:建立一个新的方程,它是两边的差:

    String diff = "(" + left + ") - (" + right + ")"

  • Parse diff with exp4j使用 exp4j 解析diff

  • Use a numerical method (eg the Secant method ) with setVariable() and evaluate() to find the solution(s).使用带有setVariable()evaluate()的数值方法(例如割线方法evaluate()来找到解决方案。

Shameless plug: If you are considering to use a different parser, take a look at this one无耻的插件:如果你正在考虑使用不同的解析器,看看这个

First, define the domain of your equations.首先,定义方程的域。 Are you talking about linear equations, polynomials, general non-linear equations, differential equations?你说的是线性方程、多项式、一般非线性方程、微分方程吗? Then define your dimension: Do you have one variable or many?然后定义你的维度:你有一个变量还是多个变量? Finally, select the appropriate solver (numerical, symbolical, Gauss, Newton etc.).最后,选择合适的求解器(数值、符号、高斯、牛顿等)。

Once you have defined this, you need to transform the syntax tree of exp4j into the format required by the solver.一旦你定义了这个,你需要将 exp4j 的语法树转换成求解器所需的格式。 However it seems that you won't be able to do this with exp4j, since it does not expose the structure of an expression as an API.但是,您似乎无法使用 exp4j 执行此操作,因为它不会将表达式的结构公开为 API。

I would advice to use a proper AST.我建议使用适当的 AST。 If you cannot do that, you can see in the implementation , that the internal structure is basically just a token list.如果你不能这样做,你可以在实现中看到内部结构基本上只是一个令牌列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM