Java синтаксический анализатор выражений, который может принимать комплексные числа в качестве переменной? - PullRequest
2 голосов
/ 18 сентября 2009

Я пишу программу на Обработка , которая преобразует комплексные числа. Тем не менее, я хочу иметь метод взятия входной строки и вычисления преобразования с использованием комплексной переменной. Например:

1/(z+1)
(z^2)/(z/2)

, где z - комплексное число. Теперь я посмотрел на JEP и некоторые примеры , но я не могу понять, позволит ли это фактически ввести z в качестве переменной (и в любом случае это не бесплатно). Есть ли анализатор выражений для Java (который работает в процессе обработки, который использует старую версию Java и не имеет обобщений), который я мог бы использовать для этого?

Если нет, может кто-нибудь указать мне основы того, как его создать?

Ответы [ 7 ]

2 голосов
/ 19 сентября 2009

Как уже упоминалось PhiLo, вы можете использовать дженерики. Попробуйте этот эскиз обработки:

import java.util.*;
java.util.List<String> list = Arrays.asList("a", "b", "c");
textFont(loadFont("UMingCN-30.vlw"));
for(int i = 0; i < list.size(); i++) {
  text(list.get(i), 5, int(i*30)+30);
}

И есть некоммерческая версия JEP (GPL). Загрузите его здесь и добавьте в свой путь к классу обработки (импортируйте его). После успешного выполнения этого вы можете использовать JEP следующим образом:

void setup() {
  org.nfunk.jep.JEP parser = new org.nfunk.jep.JEP();
  parser.addComplex();
  try {
    parser.parseExpression("(1+2*i) + (3+8*i)");
    println(parser.getComplexValue());
  } catch(Exception e) {
    e.printStackTrace();
  }
}

, который производит (ожидаемый) результат: (4.0, 10.0)

1 голос
/ 21 апреля 2016

Если по какой-то причине вам нужна большая гибкость, чем предложенные ранее «консервированные» парсеры сложных математических выражений (= полный контроль над операторами, приоритетами, построением дерева), вы можете рассмотреть мой настраиваемый парсер:

https://github.com/stefanhaustein/expressionparser

Пример кода прямой оценки для вашего случая:

static HashMap<String, Complex> variables = new HashMap<>();

/**
 * Processes the calls from the parser directly to a Complex value.
 */
static class ComplexProcessor extends ExpressionParser.Processor<Complex> {
  @Override
  public Complex infixOperator(ExpressionParser.Tokenizer tokenizer, String name, Complex left, Complex right) {
    switch (name.charAt(0)) {
      case '+': return left.plus(right);
      case '-': return left.minus(right);
      case '*': return left.times(right);
      case '/': return left.divides(right);
      case '^':
        if (right.im() != 0 || right.re() == (int) right.re()) {
          return left.pow((int) right.re());
        }
        throw new RuntimeException("Only integer exponents supported by Complex.pow().");
      default:
        throw new IllegalArgumentException();
    }
  }

  @Override
  public Complex prefixOperator(ExpressionParser.Tokenizer tokenizer, String name, Complex argument) {
    return name.equals("-") ? new Complex(0,0).minus(argument) : argument;
  }

  @Override
  public Complex numberLiteral(ExpressionParser.Tokenizer tokenizer, String value) {
    return new Complex(Double.parseDouble(value), 0);
  }

  @Override
  public Complex identifier(ExpressionParser.Tokenizer tokenizer, String name) {
    Complex value = variables.get(name);
    if (value == null) {
      throw new IllegalArgumentException("Undeclared variable: " + name);
    }
    return value;
  }

  @Override
  public Complex group(ExpressionParser.Tokenizer tokenizer, String paren, List<Complex> elements) {
    return elements.get(0);
  }

  /**
   * Creates a parser for this processor with matching operations and precedences set up.
   */
  static ExpressionParser<Complex> createParser() {
    ExpressionParser<Complex> parser = new ExpressionParser<Complex>(new ComplexProcessor());
    parser.addCallBrackets("(", ",", ")");
    parser.addGroupBrackets("(", null, ")");
    parser.addOperators(ExpressionParser.OperatorType.INFIX_RTL, 4, "^");
    parser.addOperators(ExpressionParser.OperatorType.PREFIX, 3, "+", "-");
    // 2 Reserved for implicit multiplication
    parser.addOperators(ExpressionParser.OperatorType.INFIX, 1, "*", "/");
    parser.addOperators(ExpressionParser.OperatorType.INFIX, 0, "+", "-");
    return parser;
  }
}

Пример вызова:

  variables.put("i", new Complex(0, 1));
  variables.put("z", new Complex(1, 1));

  ExpressionParser<Complex> parser = ComplexProcessor.createParser();
  System.out.println("(z^2)/(z/2):", parser.parse("(z^2)/(z/2)"));

Сам синтаксический анализатор реализован в одном Java-файле без зависимостей, поэтому для целей оценки его просто скопировать в собственный проект

1 голос
/ 10 марта 2012

Посмотрите на это: http://bracer.sourceforge.net Это моя реализация алгоритма маневрового двора, и этот синтаксический анализатор поддерживает комплексные числа.

0 голосов
/ 21 апреля 2016

Использование Apache Common Math . Это очень удобно.

Вы можете инициализировать обе реальные + мнимые части. Вы также можете инициализировать их из строки. Он поддерживает широкий спектр операций, которые вы можете выполнять с мнимыми числами.

Вот пример кода для выполнения некоторых общих операций:

package complex;
import static java.lang.String.format;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.math3.complex.Complex;
import org.apache.commons.math3.complex.ComplexFormat;
public class Do 
{
    public static void main(String[] args) 
{
     ComplexFormat format = new ComplexFormat();
    Complex lhs = new Complex(1.0, 3.0);
    Complex rhs = new Complex(2.0, 5.0);

    Complex answer = lhs.add(rhs);       // add two complex numbers
    System.out.println("Add : "+ format.format(answer));
    answer = lhs.subtract(rhs);  // subtract two complex numbers
    System.out.println("Subtract : "+ format.format(answer));
    answer = lhs.conjugate();
    System.out.println("Conjgate : "+ format.format(answer));
    double d = lhs.abs();
    System.out.println("Absolute : "+d);
    Complex first  = new Complex(1.0, 3.0);
    Complex second = new Complex(2.0, 5.0);

    answer = first.log();        // natural logarithm.
            System.out.println("Logarithm : "+ format.format(answer));
    answer = first.cos();        // cosine
            System.out.println("Cosine : "+ format.format(answer));
    answer = first.pow(second);  // first raised to the power of second
            System.out.println("Power : "+ format.format(answer));

            Complex z = new Complex(2.0,2.0);
            Complex z1 = z.reciprocal();
            System.out.println("Recipocal : "+ format.format(z1));

            System.out.println("Absoltue of 2+2i is "+z.abs());
            System.out.println("Argument of 2+2i is "+z.getArgument());

    Complex r = new Complex(6.3,9.6);
    String conj = format.format(r.conjugate());
    String reci = format.format(r.reciprocal());

    System.out.println("Conjugate : "+conj+" Recipocal : "+reci);

    //answer = lhs.abs();          // absolute value
    //answer = lhs.conjugate(rhs); // complex conjugate

    //make complex to string

    ComplexFormat format = new ComplexFormat(); // default format
    Complex c = new Complex(1.1111, 2.2222);
    String s = format.format(c); // s contains "1.11 + 2.22i"
    System.out.println(s);

    //make string to complex

    String z = "2.5+3.6i";
    Complex e = format.parse(z);
    System.out.println(e);

}    
}

Другой вариант - FrAid , если вы хотите другой вариант.

0 голосов
/ 19 сентября 2009

Вот ссылка на прямой синтаксический анализатор математических выражений (64 строки): http://javadots.blogspot.com/2008/11/arithemetic-expressions-solver-in-64.html

Настройка для удовлетворения ваших потребностей не должна быть слишком сложной

0 голосов
/ 19 сентября 2009

Вот сумасшедшее решение: java имеет встроенный движок JavaScript (я полагаю, вы можете получить к нему доступ из Processing). Теперь вы пишете класс javascript, который работает с комплексными числами (скопируйте его из здесь ). Затем перегрузите математические операторы, как указано здесь . После того, как вы можете просто вывести эту строку из Java. Это безумие, и я не уверен, что это сработает (я не знаю javascript). Может быть, это поможет найти более простое решение без разбора выражений.

0 голосов
/ 19 сентября 2009

Я бы (и на самом деле) вручную создал таблицу синтаксического анализа и использовал бы простой парсер LR или LALR для его обработки. При уменьшении вы можете выполнить расчеты. Одним из преимуществ этого является то, что легко изменить «язык» или приемлемый ввод.

...