【问题标题】:Java: solving symbolic algebraic equationsJava:求解符号代数方程
【发布时间】:2016-03-09 14:10:10
【问题描述】:

我无法将此功能添加到我的计算器应用程序中。这是我的想法:

我要解决:2x = 5 + 4x

如果我使用外部令牌库来解析方程,解决这个问题是没有问题的,但是由于我的整个程序是围绕一个调车场解析器 (EXP4J) 构建的,所以它使事情变得复杂。你可能会说我可以只在特定情况下使用令牌解析器,但是当你考虑到我有使用 EXP4J 的 FUNCTIONS 时,它变得非常纠结。

因此,虽然我可以通过简单地在这种特定情况下切换到令牌解析器来使其适用于 2x = 5 + 4x,但使用 EXP4J 的计算,例如:

2x = 5*exp4jfunc(x + 5,x) + cos(x) 完全超出我的能力范围。

有人知道如何解决这个问题吗?我什至不知道我的 CASIO 是如何解决这个问题的,因为它冻结了像 x = 9^x 这样的求解 x 方程...

【问题讨论】:

  • 解方程并不像你想象的那么容易。它与您的解析器无关。仅从数学的角度来看,除了多项式之外的任何东西都将非常难以解决。至少如果您采用一般方法。
  • 你想要的一般称为“计算机代数系统”;见en.wikipedia.org/wiki/Computer_algebra_system。这些与计算公式值的工具非常不同,因为它们必须象征性地操纵方程。这些很难构建,特别是如果您想处理许多不同类型的方程;对于每种方程类型,您需要不同的求解器技术。您可以通过查看一个非常简单的高中代数来了解实现一个需要什么:semdesigns.com/Products/DMS/SimpleDMSDomainExample.html
  • PS:写一个解析器非常容易。见stackoverflow.com/questions/2245962/…。为您的 exp4j 示例编写解析器并不难。正如我上面所说,求解器部分很难。
  • @daedsidog:有没有找到解决方案?我正在尝试解决类似的问题。例如:x*1/40+5=12 所以在这里我已经知道12 的解决方案,但我想解决x 之类的x=(12-5)*40 导致x=280

标签: java parsing


【解决方案1】:

使用symja library,您可以像这样解决您的问题:

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();
        }
    }
}

您可以查看Roots() function 的实现如何转换解析的 AST 以求解方程。

【讨论】:

    【解决方案2】:

    我对 exp4j 不是很熟悉...鉴于 Expression 类似乎无法提供对已解析结构的太多访问,因此符号方法似乎对 exp4j 并不可行。

    你可以尝试用 exp4j 代替:

    • = 处的等式拆分为leftright

    • 建立一个双方差的新方程:

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

    • 使用 exp4j 解析 diff

    • 使用带有setVariable()evaluate() 的数值方法(例如Secant method)来找到解决方案。

    无耻插件:如果您正在考虑使用不同的解析器,请查看this one

    【讨论】:

      【解决方案3】:

      首先,定义方程的域。您是在谈论线性方程、多项式、一般非线性方程、微分方程吗?然后定义你的维度:你有一个变量还是多个?最后,选择合适的求解器(数值、符号、高斯、牛顿等)。

      一旦你定义了这个,你需要将 exp4j 的语法树转换成求解器需要的格式。但是,您似乎无法使用 exp4j 执行此操作,因为它不会将表达式的结构公开为 API。

      我建议使用适当的 AST。如果你不能这样做,你可以看到in the implementation,内部结构基本上只是一个令牌列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-24
        • 2013-01-17
        • 2012-12-16
        • 2023-03-21
        • 2020-03-28
        相关资源
        最近更新 更多