线性方程的解析系数

3
在Java中,我正在尝试查找线性方程的系数,以在我的计算器应用程序中找到线性方程的解,例如:
3x +2*(6x-3) = 2 -4x 

我想要的是以形如ax+b=0的表达方式得到x的系数和常数项。

在这个特定的例子中:

coefficient = 19
constant = -8

请提出一个通用的想法。

1
它是否还能解决像 3 * x + 2 * (6 * x - 3) = 2 - 4 * x * log(sin(cos(42))^(sqrt(tan(2+atan(12)) 这样的问题?只是想知道答案是否应该是一些快速的 Integer.parseIntstring.substring 混乱,还是一个完整的计算机代数系统... - Marco13
@Marco13 这很有趣 :P 不过他确实问了一个好问题。 - Uma Kanth
一个广义的想法是编写文法。详见谷歌“antlr计算器示例”。 - Tagir Valeev
目前来说,我提出的上述方程已经足够了,你们能帮忙吗? - erluxman
消除空格,逐个字符解析,实时计算系数和常数的值。如果您以前从未使用过语法分析器,则应该是最容易理解和操作的方法。 - Deltharis
1个回答

2
如我评论中所建议的那样:这可能是任意复杂的,取决于这个解析器应该支持的内容。这里涉及到几个潜在的非常复杂和具有挑战性的任务。
第一个任务是解析本身。虽然它已经被很好地理解,并且有支持编写解析器的工具,但从头开始编写一个强大、可靠的解析器仍然是繁琐的,需要付出一些努力。
第二个任务是简化表达式。尽管可以编写一个简单的解析器(或使用现有的解析器),但人们可能(乍一看)认为需要对生成的抽象语法树进行操作,以找到实际的常量和系数 - 例如,人们可能认为需要应用分配法则、找到公共因素、将部分表达式从等式的一侧移动到另一侧等等。

幸运的是,这一切都不是必需的 :-)

您可以使用任意解析器来解析涉及到方程的表达式。最著名的解析器之一是 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接