简体   繁体   中英

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 .

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. 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.

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*exp4jfunc(x + 5,x) + cos(x) are completely beyond me.

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 ...

With the symja library you can solve your problem like this:

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.

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.

One thing you could try with exp4j instead:

  • Split the equation at = into left and right

  • Build a new equation that is the difference of both sides:

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

  • Parse diff with exp4j

  • Use a numerical method (eg the Secant method ) with setVariable() and evaluate() to find the solution(s).

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. 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.

I would advice to use a proper AST. If you cannot do that, you can see in the implementation , that the internal structure is basically just a token list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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