Как уже было сказано в моем комментарии: это может быть сколь угодно сложным, в зависимости от того, что именно этот парсер должен поддерживать. Здесь есть несколько потенциально очень сложных и сложных задач.
Первый — это анализ самого себя. Хотя это хорошо понятно и существуют вспомогательные инструменты для написания синтаксических анализаторов и прочего, было бы утомительно (и потребовало некоторых усилий) написать надежный анализатор для этих выражений с нуля.
Второй — упрощение выражения. В то время как можно написать простой парсер (или использовать существующий), можно (на первый взгляд) подумать, что необходимо выполнить манипуляции с сгенерированным 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
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