2009-09-18 18 views
2

J'écris un programme en Processing qui transforme des nombres complexes. Cependant, je veux avoir une méthode pour prendre une chaîne d'entrée et calculer la transformation en utilisant une variable complexe. Par exemple:Analyseur d'expressions mathématiques Java pouvant prendre des nombres complexes en tant que variable?

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

où z est un nombre complexe. Maintenant, j'ai regardé JEP et certains examples, mais je ne peux pas travailler si cela vous permettrait d'entrer z en tant que variable (et en tout cas ce n'est pas gratuit). Existe-t-il un analyseur d'expressions pour Java (qui fonctionne dans le traitement, qui utilise une ancienne version de Java et qui n'a pas de génériques) que je pourrais utiliser pour faire cela?

Si ce n'est pas le cas, quelqu'un pourrait-il m'indiquer les bases de la façon d'en créer un?

+2

Pour votre information, le traitement n'utilise pas « une ancienne version de Java », il fonctionne très bien avec Java 1.6. Il peut utiliser des bibliothèques Java 1.6, et si vous avez besoin de génériques dans une esquisse, vous pouvez mettre cette partie dans un fichier .java. – PhiLho

+0

Comment? Ce serait tellement utile! J'ai essayé beaucoup de déclaration d'importation mais aucun d'entre eux m'a permis de le faire. J'utilise l'IDE de traitement avec le dernier JDK de Sun. –

Répondre

2

Comme mentionné par PhiLo, vous pouvez utiliser des génériques. Essayez cette esquisse 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 here et ajoutez-le à votre chemin de classe Processing (importez-le). Après avoir fait avec succès, 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 le (attendu) de sortie: (4.0, 10.0)

+0

Pourquoi vous factureraient-ils 500 $ s'il existe une version GPL? –

+0

Merci beaucoup, ça marche bien (et les génériques économisent du temps de frappe). Je ne peux pas comprendre la divergence de 500 $/GPL cependant. –

+0

AFAIK, JEP a commencé comme une application GPL (ou une autre licence ouverte). Il y a quelque temps, ils sont devenus commerciaux et à partir de là, une ancienne version de JEP a été hébergée chez Sourceforge. Vous ne pouvez pas simplement faire payer des gens qui utilisent le logiciel GPL depuis des années. –

0

Je voudrais (et j'ai, en fait) faire manuellement une table d'analyse et utiliser un simple analyseur LR ou LALR pour le traiter. Lors d'une réduction, vous pouvez effectuer les calculs. Un avantage à cela est qu'il est facile de modifier la "langue", ou entrée acceptable.

0

Voici la solution folle: java a intégré le moteur JavaScript (je suppose que vous pouvez y accéder à partir de traitement). Maintenant, vous écrivez une classe javascript qui fonctionne avec des nombres complexes (copiez-le à partir de here). Ensuite, surchargez les opérateurs mathématiques comme indiqué here. Après que vous pouvez juste évaluer cette chaîne de Java. C'est fou et je ne suis pas sûr que ça va marcher (je ne sais pas javascript). Peut-être fera-t-il pour trouver une solution plus simple sans analyser les expressions.

1

Jetez un oeil à ceci: http://bracer.sourceforge.net il est mon implémentation de l'algorithme shunter-cour et cet analyseur sup ports numéros complexes.

0

Utilisez Apache Common Math. C'est très facile à utiliser.

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

Voici un exemple de code pour faire quelques opérations communes:

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 voulez une autre option.

1

Si pour une raison quelconque, vous avez besoin de plus de flexibilité que l'expression mathématique complexe « en boîte » parseurs proposées jusqu'à présent (= contrôle total sur les opérateurs, la priorité, la construction d'arbres), vous voudrez peut-être considérer mon analyseur configurable:

https://github.com/stefanhaustein/expressionparser

Exemple 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 invocation:

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 mis en œuvre en une seule java file sans dépendances, donc à des fins d'évaluation, il est facile de copier sur votre propre projet