Un analyseur d’expression mathématique Java pouvant prendre des nombres complexes comme variable?

StackOverflow https://stackoverflow.com/questions/1446466

Question

J'écris un programme dans le Traitement qui transforme des nombres complexes. Cependant, je souhaite avoir une méthode permettant de prendre une chaîne d'entrée et de calculer la transformation à l'aide d'une variable complexe. Par exemple:

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

où z est un nombre complexe. Maintenant, j’ai jeté un œil à JEP et à quelques exemples , mais je ne peux pas savoir si cela vous permettrait de saisir z en tant que variable (et de toute façon ce n’est pas gratuit). Existe-t-il un analyseur d'expression pour Java (qui fonctionne dans le traitement, qui utilise une ancienne version de Java et ne contient pas de génériques) que je pourrais utiliser pour cela?

S'il n'y en a pas, quelqu'un pourrait-il m'indiquer les bases de la création d'un ordinateur?

Était-ce utile?

La solution

Comme mentionné par PhiLo, vous pouvez utiliser des génériques. Essayez ce croquis de traitement:

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

Et il existe une version non commerciale de JEP disponible (GPL). Téléchargez-le ici et ajoutez-le à votre classpath Processing (importez-le). Après avoir réussi, vous pouvez utiliser JEP comme ceci:

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

qui produit la sortie (attendue): (4.0, 10.0)

Autres conseils

Jetez un coup d'œil à ceci: http://bracer.sourceforge.net C'est ma mise en œuvre de la gare de triage algorithme et cet analyseur prend en charge les nombres complexes.

Si, pour une raison quelconque, vous avez besoin de plus de flexibilité que le "Conserve". Analyseurs d’expressions mathématiques complexes suggérés jusqu’à présent (= contrôle total des opérateurs, priorité, construction de l’arborescence), vous pouvez envisager de prendre en compte mon analyseur configurable:

https://github.com/stefanhaustein/expressionparser

Exemple de code d'évaluation directe pour votre cas:

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

Exemple d'appel:

  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)"));

L'analyseur lui-même est implémenté dans un seul fichier java sans dépendances, il est donc simple de copier dans votre propre projet à des fins d'évaluation

Je voudrais (et ai en fait) créer manuellement une table d’analyse et utiliser un simple analyseur LR ou LALR pour la traiter. En cas de réduction, vous pouvez effectuer les calculs. L’un des avantages est qu’il est facile de modifier le "langage" ou les entrées acceptables.

Voici une solution folle: Java a un moteur JavaScript intégré (je suppose que vous pouvez y accéder à partir de Processing). Maintenant, vous écrivez une classe javascript qui fonctionne avec des nombres complexes (copiez-la à partir de ici ). Ensuite, surchargez les opérateurs mathématiques comme spécifié ici . Après cela, vous pouvez simplement évaluer cette chaîne à partir de Java. C'est fou et je ne suis pas sûr que ça va marcher (je ne sais pas javascript). Il sera peut-être utile de trouver une solution plus simple sans analyser les expressions.

Voici un lien vers un analyseur d'expression mathématique simple (64 lignes): http://javadots.blogspot.com/2008/11/arithemetic-expressions-solver-in-64.html

Le modifier pour répondre à vos besoins ne devrait pas être trop difficile

Utilisez les Mathématiques Apache communes . Il est très facile à utiliser.

Vous pouvez initialiser les deux parties réelles + imaginaires. Vous pouvez également les initialiser à partir d'une chaîne. Il prend en charge un large éventail d'opérations que vous pouvez effectuer avec des nombres imaginaires.

Voici un exemple de code permettant d'effectuer certaines opérations courantes:

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

}    
}

Une autre alternative est FrAid , si vous souhaitez une autre option.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top