Коэффициент разбора линейного уравнения

В java я пытаюсь найти коэффициенты линейного уравнения, чтобы найти решение линейного уравнения в моем приложении калькулятора, например:

3x +2*(6x-3) = 2 -4x 

то, что я умираю, чтобы получить, это коэффициенты x и константа в форме ax+b =0 ,

в этом конкретном примере

coefficient = 19
constant = -8

Пожалуйста, предложите общую идею


person erluxman    schedule 19.08.2015    source источник
comment
Должен ли он также решить это для чего-то вроде 3 * x + 2 * (6 * x - 3) = 2 - 4 * x * log(sin(cos(42))^(sqrt(tan(2+atan(12))? Просто чтобы знать, должен ли ответ быть какой-то быстрый Integer.parseInt и string.substring беспорядок, или полноценная система компьютерной алгебры...   -  person Marco13    schedule 19.08.2015
comment
@ Marco13, это было забавно :P Но это был хороший вопрос.   -  person Uma Kanth    schedule 19.08.2015
comment
Обобщенной идеей было бы написать грамматику. Google «пример калькулятора antlr» для деталей.   -  person Tagir Valeev    schedule 19.08.2015
comment
Для текущего, приведенного выше уравнения, которое я спросил, было бы достаточно, вы можете помочь, ребята?   -  person erluxman    schedule 19.08.2015
comment
Удаляйте пробелы, разбирайте посимвольно, вычисляйте значения коэффициента и константы на лету. Должно быть проще всего сделать и понять, если вы никогда раньше не использовали анализатор грамматики.   -  person Deltharis    schedule 19.08.2015


Ответы (1)


Как уже было сказано в моем комментарии: это может быть сколь угодно сложным, в зависимости от того, что именно этот парсер должен поддерживать. Здесь есть несколько потенциально очень сложных и сложных задач.

Первый — это анализ самого себя. Хотя это хорошо понятно и существуют вспомогательные инструменты для написания синтаксических анализаторов и прочего, было бы утомительно (и потребовало некоторых усилий) написать надежный анализатор для этих выражений с нуля.

Второй — упрощение выражения. В то время как можно написать простой парсер (или использовать существующий), можно (на первый взгляд) подумать, что необходимо выполнить манипуляции с сгенерированным AST, чтобы найти фактическую константу и коэффициент - например, можно было бы подумать, что придется применить законы распределения, найти общие множители, переложить частное выражение из одной части уравнения в другую и т.д.


К счастью, все это не нужно :-)

Вы можете использовать произвольный синтаксический анализатор для анализа выражений, которые участвуют в уравнении. Одним из самых известных парсеров является JEP. , синтаксический анализатор выражений Java (это не рекомендация — я просто знал его, и, похоже, он работает хорошо). Как следует из названия, это всего лишь анализатор выражений, а не анализатор уравнений. Но уравнение можно просто разделить на =, чтобы получить два выражения, которые можно анализировать по отдельности.

Двух выражений было бы недостаточно, чтобы найти коэффициент и константу. Но здесь в игру вступает небольшой (грязный?) трюк: вы можете получить коэффициент и константы, вычисляя эти выражения. В частности, вы можете один раз установить x=0 для определения постоянной части левой и правой стороны соответственно. Затем вы можете установить x=1, оценить результирующее выражение и вычесть константу, чтобы получить коэффициент.

Из коэффициентов и констант обеих сторон можно вычислить коэффициент и константу всего уравнения. Это реализовано здесь как MCVE:

import org.nfunk.jep.JEP;

public class LinearEquationParser
{
    private double coefficient;
    private double constant;

    public static void main(String[] args)
    {
        runTest("3x = 5");
        runTest("3x +2*(6x-3) = 2 -4x");
        runTest("3x + 2*(6x -sin(3))=cos(2)-4*x*log(tan(43))");
    }

    private static void runTest(String s)
    {
        System.out.println("Input: "+s);

        LinearEquationParser p = new LinearEquationParser();
        p.process(s);

        System.out.println("Coefficient: "+p.getCoefficient());
        System.out.println("Constant   : "+p.getConstant());
        System.out.println();
    }

    public void process(String s)
    {
        JEP jep = new JEP();
        jep.setImplicitMul(true);
        jep.addStandardFunctions();
        jep.addStandardConstants();
        jep.addVariable("x",  0.0);

        String s0 = s.substring(0, s.indexOf("="));
        String s1 = s.substring(s.indexOf("=")+1, s.length());

        jep.parseExpression(s0);
        if (jep.hasError())
        {
            throw new IllegalArgumentException(jep.getErrorInfo());
        }

        jep.addVariable("x",  0.0);
        double constant0 = jep.getValue();
        jep.addVariable("x",  1.0);
        double value0 = jep.getValue();

        jep.parseExpression(s1);
        if (jep.hasError())
        {
            throw new IllegalArgumentException(jep.getErrorInfo());
        }

        jep.addVariable("x",  0.0);
        double constant1 = jep.getValue();
        jep.addVariable("x",  1.0);
        double value1 = jep.getValue();

        constant = constant0 - constant1;
        coefficient = (value0 - constant0) - (value1-constant1);
    }

    public double getCoefficient()
    {
        return coefficient;
    }

    public double getConstant()
    {
        return constant;
    }

}

Вывод по желанию:

Input: 3x = 5
Coefficient: 3.0
Constant   : -5.0

Input: 3x +2*(6x-3) = 2 -4x
Coefficient: 19.0
Constant   : -8.0

Input: 3x + 2*(6x -sin(3))=cos(2)-4*x*log(tan(43))
Coefficient: 15.7024963786418
Constant   : 0.13390682042740798
person Marco13    schedule 28.08.2015