hallöchen
kennt jemand gut tutorials oder beispiel code in java zum schreiben eines parsers der mir einen string in mathematische ausdrücke umwandelt bzw. ausrechnet.
also sowas: "(1+((((2+3)*5)/6)*7))" oder auch sowas "5^3/3+cos(0.5)"
ich hab mir bishher folgendes überlegt, ich les die operanden (zahlen) in einen stack ein und die operatoren (+,*,- usw) in n anderen stack. wenn eine öffnende klammer kommt ruf ich meinen parser rekursiv auf und teste dann weiter. wenn n schliessende klammer kommt nehm ich die 2 obersten werte ausm operanden-stack und rechne die mit dem obersten wert ausm operatoren-stack aus. dann schreib ich das ergebnis zurück auf den operandenstack und geh ne rekursionsstufe nach oben...
aber irgendwie klappts noch ned. vor allem muss ich ja falls keine klammer kommt im string immer um einen index weiterlaufen. aber da gibts mir dann ne endlos-schleife (siehe code)
also... wenn mir jmd n tipp zu meinem code geben könnte oder n allgemeinen lösungsvorschlag oder eben ein tutorial wär ich echt froh drum!
kennt jemand gut tutorials oder beispiel code in java zum schreiben eines parsers der mir einen string in mathematische ausdrücke umwandelt bzw. ausrechnet.
also sowas: "(1+((((2+3)*5)/6)*7))" oder auch sowas "5^3/3+cos(0.5)"
ich hab mir bishher folgendes überlegt, ich les die operanden (zahlen) in einen stack ein und die operatoren (+,*,- usw) in n anderen stack. wenn eine öffnende klammer kommt ruf ich meinen parser rekursiv auf und teste dann weiter. wenn n schliessende klammer kommt nehm ich die 2 obersten werte ausm operanden-stack und rechne die mit dem obersten wert ausm operatoren-stack aus. dann schreib ich das ergebnis zurück auf den operandenstack und geh ne rekursionsstufe nach oben...
aber irgendwie klappts noch ned. vor allem muss ich ja falls keine klammer kommt im string immer um einen index weiterlaufen. aber da gibts mir dann ne endlos-schleife (siehe code)
Code:
private void parseAndDetermine(String s, int i) {
while (i < s.length()) {
if (s.charAt(i) == '(') parseAndDetermine(s, ++i);
// ausrechnen bei schliessender klammer
if (s.charAt(i) == ')') {
// operator aus operator-stack holen
String s_operator = (String) operators.pull();
// basic-operatoren sind: +,-,*,/,^
if (isBasic(s_operator)) {
// die obersten beiden werte holen
Double D_b = (Double) operanden.pull();
Double D_a = (Double) operanden.pull();
// und
// ausrechnen
Double D_result = determineBasic(s_operator, D_a, D_b);
// resultat
// zurück
// auf
// stack
operanden.push(D_result);
}
// der rest: sin,
// cos, tan, exp
// usw.
else {
Double D_a = (Double) operanden.pull();
Double D_result = determineAdvanced(s_operator, D_a);
operanden.push(D_result);
}
// ne stufe nach
// oben
return;
}
if (s.charAt(i) == 'x') {
operanden.push(new Double(actX));
i++;
}
// zahlen in den operanden stack
if (s.charAt(i) >= 0 && s.charAt(i) <= 9) {
operanden
.push(new Double(Double.parseDouble(s.substring(i, i))));
i++;
}
// jetzt alle operatoren: in den
// operatoren-stack
if (s.charAt(i) == '+') {
operators.push(new String("+"));
i++;
}
if (s.charAt(i) == '-') {
operators.push(new String("-"));
i++;
}
if (s.charAt(i) == '*') {
operators.push(new String("*"));
i++;
}
if (s.charAt(i) == '/') {
operators.push(new String("/"));
i++;
}
if (s.charAt(i) == '^') {
operators.push(new String("^"));
i++;
}
if (s.charAt(i) == 'l') {
operators.push(new String("ln"));
i++;
}
if (s.charAt(i) == 'e') {
if (s.regionMatches(true, i, "exp", 0, 3))
operators.push(new String("exp"));
else
operanden.push(new Double(Math.E));
i++;
}
if (s.charAt(i) == 's') {
if (s.regionMatches(true, i, "sin", 0, 3))
operators.push(new String("sin"));
else
operators.push(new String("sqrt"));
i++;
}
if (s.charAt(i) == 'c') {
operators.push(new String("cos"));
i++;
}
if (s.charAt(i) == 't') {
operators.push(new String("tan"));
i++;
}
if (s.charAt(i) == 'a') {
if (s.regionMatches(true, i, "asin", 0, 4))
operators.push(new String("asin"));
if (s.regionMatches(true, i, "acos", 0, 4))
operators.push(new String("acos"));
if (s.regionMatches(true, i, "atan", 0, 4))
operators.push(new String("atan"));
i++;
}
System.out.println("i= " + i);
operators.showStack();
operanden.showStack();
}
}
private boolean isBasic(String s) {
if (s.equals("+"))
return true;
else if (s.equals("-"))
return true;
else if (s.equals("*"))
return true;
else if (s.equals("/"))
return true;
else
return false;
}
private Double determineBasic(String s, Double a, Double b) {
double d_a = a.doubleValue();
double d_b = b.doubleValue();
double d_result = 0;
Double result;
if (s.equals("+")) d_result = d_a + d_b;
if (s.equals("-")) d_result = d_a - d_b;
if (s.equals("*")) d_result = d_a * d_b;
if (s.equals("/")) d_result = d_a / d_b;
if (s.equals("^")) d_result = Math.pow(d_a, d_b);
return result = new Double(d_result);
}
private Double determineAdvanced(String s, Double a) {
double d_result = 0;
double d_a = a.doubleValue();
Double result;
if (s.equals("sin")) d_result = Math.sin(d_a);
if (s.equals("cos")) d_result = Math.cos(d_a);
if (s.equals("tan")) d_result = Math.tan(d_a);
if (s.equals("asin")) d_result = Math.asin(d_a);
if (s.equals("acos")) d_result = Math.acos(d_a);
if (s.equals("atan")) d_result = Math.atan(d_a);
if (s.equals("exp")) d_result = Math.exp(d_a);
if (s.equals("ln")) d_result = Math.log(d_a);
if (s.equals("sqrt")) d_result = Math.sqrt(d_a);
return result = new Double(d_result);
}
Code:
import java.util.Vector;
public class Stack
{
private Vector stack;
public Stack(int size)
{
stack = new Vector(size);
}
public void push(Object obj)
{
stack.insertElementAt(obj, 0);
}
public Object pull()
{
Object obj;
obj = stack.elementAt(0);
stack.remove(0);
return obj;
}
public void showStack()
{
for (int i=0; i<stack.size(); i++)
{
System.out.println("|"+(String)stack.elementAt(i)+"|");
}
System.out.println("____");
}
public boolean isEmpty()
{
return stack.isEmpty();
}
}
also... wenn mir jmd n tipp zu meinem code geben könnte oder n allgemeinen lösungsvorschlag oder eben ein tutorial wär ich echt froh drum!