# Intelligentes Erstellen von Formel mit unbekannter Variable



## Cru (29. Mrz 2011)

Hallo Zusammen,

ich habe ein (wahrscheinlich) recht simples Problem und komme grade nicht weiter.

Ziel soll es sein, eine Formel zusammen zu stellen, die eine bestimmte Form aufweist:


```
y = (a) + (b*(x - xi)) + (c*((x - xi)^2)) + (d*((x - xi)^3))
```

Gegeben werden a, b, c, d und xi. Die Variable x soll als String in der Formel überleben.
Eine mögliche Lösung könnte z.B. sein:


```
y = 4.0 + 3.5x  + 4.5(x - 2)^2 - 5.0(x + 3.5)^3
```

Die gegeben Variablen sind in Arrays vorhanden.
Mein Problem ist, wie bekomm ich möglichst einfach eine richtige Formel zustande, die auch ein wenig "intelligent" agiert, d.h. bei *0 einen bestimmten Teil der Formel weglässt?

Mein erster Ansatz war die Nutzung von Jep Java, eine nette Gehhilfe, die mathematische Formeln parst. Nur leider bekomm ich keine Gleichung zusammen, die mein "x" als String stehen lässt.

Hier mal mein Code:

```
public ArrayList<Spline> erstelleFormeln() throws JepException {
		arrlSplines = new ArrayList<Spline>(n);

		Jep jep = new Jep();
		jep.setAllowUndeclared(true);

		for (int j = 0; j <= n - 1; j++) {
			Spline s = new Spline();
			s.setX1(arrlPunkte.get(j).getX());
			s.setX2(arrlPunkte.get(j + 1).getX());

			jep.addVariable("a", arrA[j]);
			jep.addVariable("b", arrB[j]);
			jep.addVariable("c", arrC[j]);
			jep.addVariable("d", arrD[j]);
			jep.addVariable("xi", arrlPunkte.get(j).getX());
			jep.addVariable("x", "x");
			jep.addVariable("h2", "^2");
			jep.addVariable("h3", "^3");

			jep.parse("(a) + (b*(x - xi)) + (c*((x - xi) + h2)) + (d*((x - xi) + h3))");

			Object evaluate = jep.evaluate();
			s.setFormel(String.valueOf(evaluate));

			arrlSplines.add(j, s);
		}
		return arrlSplines;
```

Vielen Dank schonmal für mögliche Hilfe.


EDIT:

Fehler:
com.singularsys.jep.functions.IllegalParameterException: -: lllegal parameter x(String) parameter no 0

...


----------



## AmunRa (30. Mrz 2011)

Ich glaub da machst du noch meht fehler als nur bei X

denn auch die h2 und h3 sind nicht richtig. Was würde denn heraus kommen, wenn du es einsetzt.


```
(a) + (b*(x - xi)) + (c*((x - xi) + h2)) + (d*((x - xi) + h3))
(a) + (b*(x - xi)) + (c*((x - xi) + ^2)) + (d*((x - xi) + ^3))
```

und das ist einfach mathematisch nicht korrekt.

und natürlich musst du für x einen WErt einsetzen , das du ja sonst dieses Formel nicht ausrechnen kannst.
oder was möchtest du machen?

da hilft dir auch die Methode setAllowUndeclared nichts 


			
				Javadoc hat gesagt.:
			
		

> Note this only affects the parsing stage, EvaluationException will still be thrown when trying to evaluate a variable with an undefined value.


----------



## Cru (30. Mrz 2011)

Was ich als "Lösung" möchte ist die Gleichung mit "x".

Für die gegeben Variablen sind negative/positive Werte zulässig, aber auch 0.
Da "x" als String natürlich in der endgültigen Formel bleiben soll suche ich eigentlich nur nach einer Logik, die meine Gleichung automatisiert mit Werten füllt und dabei mathematisch korrekt bleibt.

D.h. 0*x = 0, usw...

Die "Formel" kann man als Teil einer Gleichung ansehen.

Bzgl. h2 und h3 war das nur ein Versuch. hier ist zu entnehmen wie die verschiedenen mathematischen Operatoren mit verschiedenen Typen arbeiten. y^x geht z.B. nicht als String, genau so wenig y-x (daher die Fehlermeldung).

Da mir Jep eigentlich ziemlich gut vor kommt, kann ich mir nicht vorstellen das eine einfache Gleichung mit 2 Unbekannten damit nicht zu lösen sei?
Nichts destotrotz such ich eigentlich nur eine Algorithmus, der mir die Gleichung zusammenstellt (mit mathematischer Richtigkeit).


----------



## AmunRa (30. Mrz 2011)

Du möchtest also nachhernur einen String haben, in dem die Werte für a b usw eingesetzt sind und eben die Variablen die noch nicht gesetzt sind stehen lässt.


----------



## Cru (30. Mrz 2011)

Genau 

Nur soll dieser String mathematisch korrekt sein.


----------



## Gonzo17 (30. Mrz 2011)

Kenne mich mit dem, was du da benutzt hast, nicht aus, aber würde es selbst einfach so umsetzen.

Erstelle eine Klasse "Variable" mit einem Konstruktor Variable(String) und einem Konstruktor Variable(String, Object). Der String ist jeweils der Name der Variable, der muss immer übergeben werden, das Object ist eben der Wert der Variable.

Wenn du weißt, dass es immer ein int oder float ist, kannst du statt Object natürlich auch den entsprechenden Typ nehmen (zB BigInteger). 

Wichtig ist auf jeden Fall noch, dass die Methode toString() überschrieben wird. Ist der Wert der Variable nicht gesetzt, dann gibst du den Namen zurück, ansonsten eben den Wert.

Das wars eigentlich schon. Du kannst dann natürlich, wenn du das willst, noch weitere Methoden zu den Variablen hinzufügen (zB Getter/Setter), um damit noch zu rechnen oder Werte auszutauschen oder zu löschen. Wenn du jetzt zB 
	
	
	
	





```
Variable a = new Variable("a", 2);
```
 erstellst und später 
	
	
	
	





```
a.toString()
```
 aufrufst, dann wird 2 ausgegeben. Setzt du keinen Wert, wird a ausgegeben.


----------



## AmunRa (30. Mrz 2011)

Wie gesagt das von dir gewünschte kann Jep* glaub ich* so nicht, dazu gibt es dann eine Erweiterung "AutoAbacus". zumindest so hab ich das ganze auf deren Hompage gelesen.

ich würde es auch selbst lösen, wenn du noch genau schreibst was du machen möchtest, 
( welche eingabe dein Program hat und welche ausgaben du dann damit machen möchtest, wie du es weiter verarbeiten möchtest) können wir dir hier sicher ein Paar tips geben.


----------



## Cru (30. Mrz 2011)

Gonzo interessante Idee, wird Jep aber nicht unterstützen ;(

Um etwas weiter auszuholen, geht es um die Berechnung von Splines (Polynomfunktionen).
Eingabe sind Koordinatenpaare (x/y) beliebiger Menge. Ein Spline ist die Funktion die zwischen z.B. x1 und x2 liegt. Die X-Werte der Koordinaten dürfen nicht gleich sein.

Die Berechnung der Splines läuft über Matrizen (in Arrays implementiert). Die Arrays werden mit einem Algorithmus gefüllt (funktioniert!) und nun müssen die Werte aus den 4 Arrays a, b, c und d zusammen mit den X-Koordinaten nur noch in die Formel gebracht werden (siehe 1. Post). Das Resultat ist die Formel des Splines (kommt in eine ArrayList vom Typ Spline; Spline beinhaltet String Formel und double x1 und x2).

Bei z.B. 5 Koordinatenpaaren gibt es 4 Splines. Ziel ist die Ausgabe von welchen X-Werten der Spline verläuft und wie seine jeweilige Formel lautet.

An sich hapert's nur an der Zusammenstellung mit den Werten aus den Arrays...


----------



## Cru (30. Mrz 2011)

Gonzo interessante Idee, wird Jep aber nicht unterstützen ;(

Um etwas weiter auszuholen, geht es um die Berechnung von Splines (Polynomfunktionen).
Eingabe sind Koordinatenpaare (x/y) beliebiger Menge. Ein Spline ist die Funktion die zwischen z.B. x1 und x2 liegt. Die X-Werte der Koordinaten dürfen nicht gleich sein.

Die Berechnung der Splines läuft über Matrizen (in Arrays implementiert). Die Arrays werden mit einem Algorithmus gefüllt (funktioniert!) und nun müssen die Werte aus den 4 Arrays a, b, c und d zusammen mit den X-Koordinaten nur noch in die Formel gebracht werden (siehe 1. Post). Das Resultat ist die Formel des Splines (kommt in eine ArrayList vom Typ Spline; Spline beinhaltet String Formel und double x1 und x2).

Bei z.B. 5 Koordinatenpaaren gibt es 4 Splines. Ziel ist die Ausgabe von welchen X-Werten der Spline verläuft und wie seine jeweilige Formel lautet.

An sich hapert's nur an der Zusammenstellung mit den Werten aus den Arrays...

Edit: Jep war nur so eine Idee am Rande, weil ich nicht weiterkam...

Edit2: Kann jmd bitte den Vorpost löschen? War nicht beabsichtigt...


----------



## Gonzo17 (30. Mrz 2011)

Cru hat gesagt.:


> Gonzo interessante Idee, wird Jep aber nicht unterstützen ;(





Cru hat gesagt.:


> Edit: Jep war nur so eine Idee am Rande, weil ich nicht weiterkam...



Dann machs doch so, wenn du Jep nicht brauchst. 

Du könntest ja theoretisch noch weiter gehen und ein Objekt "Formula" (falls man das so auf englisch benennt) erstellen, das dir Formeln mit beliebigen Objekten des Typs "Variable" darstellt.


----------



## Cru (30. Mrz 2011)

Hm ich versteh nicht ganz wozu mich das ganze dann führt?

Wenn ich das richtig verstehe würde dann in etwa das gleiche rauskommen, wenn ich die Daten einfach alle in einen String stecke.
Das Problem, dass dieser String dann nicht zwangsläufig mathematisch korrekt ist existiert ja dann immernoch?


----------



## Gonzo17 (30. Mrz 2011)

Kennst du die BNF? Du kannst einen mathematischen Ausdruck damit recht einfach beschreiben und auch die Vorrangregeln (Punkt vor Strich) je nach Umsetzung berücksichtigen (was du ja offensichtlich auch willst). In der Uni macht man da standardmäßig sogar ne Aufgabe, die genau solche mathematischen Ausdrücke baut.

Wenn man sowas hat, dann ist es 'relativ' einfach daraus ein paar Klassen zu schreiben.


----------



## Cru (30. Mrz 2011)

Chomsky-Hierarchie ist mir natürlich ein Begriff, BNF hab ich allerdings noch nicht gehört. Ich werde mir das mal anschauen...

Ok, ich hab mir das mal angeschaut und hab versucht das in der BNF darzustellen. Resultat:


```
<Formel> ::= <Teil A> <Operator> <Teil B> <Operator> <Teil C> <Operator> <Teil D>
<Operator> ::= + | - | * | / | ^ |
<Klammer> ::= ( | ) |
<Teil A> ::= Array(a) |
<Teil B> ::= Array(b) <Operator> <Klammer> x <Operator> Array(x) <Klammer> | Array(b) x | 
<Teil C> ::= Array(c) <Operator> <Klammer> <Klammer> x <Operator> Array(x) <Klammer> <Operator> 2 <Klammer> | Array(c) x <Operator> 2 | 
<Teil D> ::= Array(d) <Operator> <Klammer> <Klammer> x <Operator> Array(x) <Klammer> <Operator> 3 <Klammer> | Array(d) x <Operator> 3 |
```

Zwischenfrage: Bin ich auf dem Holzweg?^^


----------



## Gonzo17 (30. Mrz 2011)

Ok, bist schon ein wenig auf dem Holzweg. 

Hab dir mal aus meinem Informatik-Skript kopiert, wie wir das gemacht haben:


```
1) E ::= E + T 
2) E ::= T
3) T ::= T * F 
4) T ::= F
5) F ::= ( E ) 
6) F ::= i
```

Hier bindet ein * stärker als ein +. - und / kann man da in der entsprechenden Zeile ergänzen. i ist eine beliebige Zahl. E wäre eine Summe, T ein Produkt, wobei eine Summe auch ein das Ergebnis eines Produkts sein kann und ein Produkt kein eine Zahl oder eine geklammerte Summer sein.

Ehrlich gesagt weiß ich zwar nicht mehr, was ich mir dabei im Bezug auf Java gedacht hab, aber vielleicht liegts an der Uhrzeit.  Das ist auf jeden Fall eine eindeutige Grammatik, auch wenn sie nicht die LL(1)-Bedingung erfüllt (falls dir das was sagt), aber das sollte für deine Zwecke wohl erstmal egal sein schätze ich. Hoffe dir hilft das.

Also um den Vorschlag oben umzusetzen, kann man dann eine Klasse 'Sum' mit den Konstruktoren Sum(Sum, Product), einer Klasse 'Product' mit Product(Product, Expression) und Product(Expression) und dann eben Expression(Sum) und Expression(Variable). Wobei ich jetzt nicht weiß, ob Expression richtig ist, aber im Grunde gehts darum. Und eine Formel wäre dann eben ein beliebiger Ausdruck, also entweder E, T oder F. Und wie du dann mit den entsprechenden Ausdrücken umgehst, zum Beispiel dass ein 0 * x als 0 angezeigt wird, kannst du ja dann in der entsprechenden Klasse implementieren.


----------



## Cru (31. Mrz 2011)

An sich ist meine Logik schon recht rentabel, kommt ja in etwa aufs Gleiche raus wie bei dir.

Aber ich denke mittlerweile versteh ich worauf du hinauswillst und werde den Vorschlag, wenns bei mir zeitlich passt am Nachmittag umsetzen und dazu ein paar Unittests.

Danke schonmal für die Unterstützung!


----------



## Gonzo17 (31. Mrz 2011)

Bei dir gibts aber (auf den ersten Blick) zumindest ein Problem, vor allem wenn du es mathematisch korrekt haben willst. Und zwar die Bindung der entsprechenden Operatoren. Bei dir binden alle Operatoren gleich, wie also auswerten, wenn da steht a + b * c? In meinem Fall ist es klar, wenn es Sum(a, Product(b, c)) ist, dann ist es mathematisch korrekt, andersrum funktioniert es garnicht, weil ich nicht Product(Sum(a, b), c) schreiben darf. Das ist (aus meiner Sicht) eben der ganz große Vorteil so einer Schreibweise.

Wie gesagt, du willst es ja später auch auswerten und dabei sollte natürlich auch das richtige rauskommen, wenn da x + 0 * 3 steht.  Du kannst meinen Ansatz eben auch beliebig erweitern, wenn du das Prinzip verstanden hast. Je "tiefer" ein Operator steht, desto stärker bindet er. Am stärksten binden natürlich die Klammern, die können ja ganze Ausdrücke enthalten.

Edit:
So gern ich dir übrigens auch helfe, ich beanspruche keineswegs die beste Lösung anzubieten, möglicherweise gehts auch viel viel einfacher oder Jep kann das tatsächlich. Falls also jemand einen anderen/besseren Vorschlag hat, kann man den auch gerne diskutieren.


----------



## Cru (31. Mrz 2011)

Ok, ich denke ich verstehe wie das ganze funktionieren soll, allerdings henkt es bei mir grade programmiertechnisch :/

Eine kleine Gehhilfe fände ich super, wenn das nicht zuviel verlangt ist. Mir reicht an sich der Ansatz (z.B. das gegebene Bsp.).

Wäre super!


----------



## muckelzwerg (31. Mrz 2011)

Sorry, wenn ich nochmal so dazwischenfunke. Ich hab nicht wirklich verstanden, was Du eigentlich machen willst. Es geht nur um einen String der die konkreten Parameter für den kubischen Spline anzeigt? Also da soll gar nichts mit gerechnet werden, oder wie?


----------



## Cru (31. Mrz 2011)

muckelzwerg hat gesagt.:


> Sorry, wenn ich nochmal so dazwischenfunke. Ich hab nicht wirklich verstanden, was Du eigentlich machen willst. Es geht nur um einen String der die konkreten Parameter für den kubischen Spline anzeigt? Also da soll gar nichts mit gerechnet werden, oder wie?



Das was ich haben will ist der String, korrekt. Aber um diesen String zu bekommen muss ich mit den gegeben Werten rechnen.


----------



## muckelzwerg (31. Mrz 2011)

Welche Umformungen kommen denn in Frage? Xi kann 0 sein, dann hast Du "Koefizient * x" da stehen.
Ansonsten könnte noch ein Koeffizient selbst 0 sein. Dann hättest Du "0" da stehen.
Kannst Du jetzt nicht ein Objekt für "k * (x + xi)" bilden, das in seiner toString Methode nur diese beiden Fälle prüft?
Rechnen musst/kannst Du doch eigentlich gar nichts.


```
class Poly{
	private double k;
	private double xi;

	public Poly(double k, double xi){
		this.k = k;
		this.xi = xi;
	}
	
	public String toString(){
		String ret = "";
		if( k == 0 )
			ret = "";
		else if( xi == 0 )
			ret = "" + k + "*x";
		else if( xi < 0 )
			ret = "" + k + "*(x" + xi + ")";
		else ret = "" + k + "*(x+" + xi + ")";
		
		if( k > 0 )
			ret = "+" + ret;
		return ret;
	}
}

double a = 4.0;
Poly p1 = new Poly(3.5, 0);
Poly p2 = new Poly(4.5, -2);
Poly p3 = new Poly(-5.0, -3);

System.out.println(a + " " + p1 + " " + p2 + "^2 " + p3 + "^3");
```

So "irgendwie"? Hat natürlich Schwachstellen. Z.B. kannst Du das Leerzeichen zwischen den Operatoren und Koeffizienten nicht so leicht setzen. (wäre nochmal eine Abfrage mehr)
Eigentlich müsstest Du für den ganzen Ausdruck den Baum basteln und dann rekursiv auflösen. Aber wer will das schon?

Oder ich hab immernoch nicht kapiert, was Du willst und mach mich grad lächerlich.


----------



## feiste (31. Mrz 2011)

also ich habs jetzt so verstanden:


```
public class Formel
{
   public class Formel
{
   String p1;
   String p2;
   String p3;
   String p4;
   String p5;
   String formel;
   
    public Formel(double a, double b, double c, double d, double xi)
    {
       
        if(a == 0)
        { p1 = "" ;}
        else
        {p1 = ""+a+" + "; }
        if(b == 0)
        { p2 = "" ;}
        else
           {p2 = b+"*(x - " + xi +") + "; }
        
        if(c == 0)
        { p3 = "";}
        else
        { p3 = c+"*((x - " + xi+")^2) + ";}
    
        if(d == 0)
        { p4 = "";}
        else
        { p4 = d+"*((x - " + xi+")^3)";}
    
        if(a==0 && b==0 && c==0 && d==0)
        {formel = ("y = 0");}
        else
        {formel = ("y = " +p1 + p2 + p3 + p4);}
        
        System.out.println(formel);
       
    }
```

hab ich es richtig verstanden?
also wenn z.B b = 0 ist 
dann wird b*(x - xi)  auch nicht angezeigt.
nur xi hab ich noch nicht eingebaut
also wenn xi = 0
dann wirds so angezeigt
b*(x - 0.0)

kannst ja dann noch selber einbaun


----------



## muckelzwerg (31. Mrz 2011)

Vielleicht hätten wir der Vollständigkeit halber mal die Prints dazuschreiben sollen. -_-

```
4.0 +3.5*x +4.5*(x-2.0)^2 -5.0*(x-3.0)^3
```


----------



## feiste (31. Mrz 2011)

> Eine mögliche Lösung könnte z.B. sein:
> 
> 
> ```
> ...



@ Cru 
was ich an deinem Beispiel hier nicht verstehe ist
wieso hat dein "xi" den unterschiedliche Werte?
0; 2; -3.5


----------



## feiste (31. Mrz 2011)

muckelzwerg hat gesagt.:


> Vielleicht hätten wir der Vollständigkeit halber mal die Prints dazuschreiben sollen. -_-
> 
> ```
> 4.0 +3.5*x +4.5*(x-2.0)^2 -5.0*(x-3.0)^3
> ```




```
y = 1.0 + 2.0*(x - 5.0) + 3.0*((x - 5.0)^2) + 4.0*((x - 5.0)^3)
```

a=1, b=2, c=3, d=4, xi=5


----------



## muckelzwerg (31. Mrz 2011)

Ist nicht meins. Das sind die Werte aus dem ersten Beitrag. Ok, statt der 3.5 hab ich 3.0 getippt. 
Und ich seh grade dass die Vorzeichen noch getauscht werden müssen. Naja, kann der Chef dann selbst machen, wenn er es denn überhaupt so macht.


----------



## feiste (31. Mrz 2011)

muckelzwerg hat gesagt.:


> Ist nicht meins. Das sind die Werte aus dem ersten Beitrag. Ok, statt der 3.5 hab ich 3.0 getippt.
> Und ich seh grade dass die Vorzeichen noch getauscht werden müssen. Naja, kann der Chef dann selbst machen, wenn er es denn überhaupt so macht.



Jep die Frage war an Cru gedacht.
Das Beispiel stammt ja von ihm.


----------



## muckelzwerg (1. Apr 2011)

Na, das wird er nur als Beispiel so geschrieben haben, damit man sieht, wie der String aufgebaut sein könnte.
Für den Spline braucht er das eigentlich nicht.


----------



## JohannisderKaeufer (1. Apr 2011)

Warum nicht einfach auflösen,
Koeffizienten bestimmen
und daraus die Formel basteln?

```
y = (a) + (b*(x - xi)) + (c*((x - xi)^2)) + (d*((x - xi)^3))

x[0] = a + (b* -xi) + (c * xi²) + (d * (-xi)³)

x[1] = b* x + 2 * c* -xi + 3 * d * xi²

x[2] = c - 3 * d * xi

x[3] = d

first = true;
result = "y = ";
for(int i = 0; i < x.length;i++){
if(x[i] !=0){
  if(first){
    first = false;
    if(x[i]<0){
      result += "-";
    }
  }else{
    result += (x[i]>0)? "+" : "-";
  }
  result += x[i];
  if(i == 1){
    result += "x";
  }
  if(i > 1){
    result += "x^"+i;
  }
}
```

In der Berechnung steckt übrigens ein Muster!

Pascalsches Dreieck
11111
1234
136
14
1


----------



## muckelzwerg (1. Apr 2011)

Er hat ja nicht mehr Koeffizienten bei den Splines. Aber mach mal ein funktionierendes Beispiel draus, vielleicht können wir da eine nette Standardfunktion basteln.


----------



## Cru (1. Apr 2011)

"Rechnen" muss man an sich schon, da es mathematisch korrekt und gewissermassen gekürzt werden soll, so kann ein Ergebnis z.B. 
	
	
	
	





```
3,1429(x-1)^3 - 4,2857(x-1)^2 - 0,8571(x-1) + 2
```
 in der Form sein, allerdings gekürzt ausgerechnet sieht es dann so aus: 
	
	
	
	





```
3,1429x^3 - 13,7143x^2 + 17,1429x - 4,5714
```
.


----------



## feiste (1. Apr 2011)

Cru hat gesagt.:


> allerdings gekürzt ausgerechnet sieht es dann so aus:
> 
> 
> 
> ...



in dem Fall wäre dann xi: 0  oder?

schau dir mal meinen code an 
der müsste so stimmen.


----------



## Cru (1. Apr 2011)

Sorry, dass ich mich erst jetzt melde.

feiste, wenn ich dein Bsp. erweitern würde, würde es klappen, dass die Daten in die gewünschten Form gebracht werden.



			
				feiste hat gesagt.:
			
		

> @ Cru
> was ich an deinem Beispiel hier nicht verstehe ist
> wieso hat dein "xi" den unterschiedliche Werte?
> 0; 2; -3.5



Das war natürlich mein Fehler, die Werte für xi müssen natürlich identisch sein.



			
				feiste hat gesagt.:
			
		

> in dem Fall wäre dann xi: 0 oder?



Nein, xi ist 1!

Und so komme ich zum letztendlichen Problem, und zwar der Vereinfachung, nachdem die Gleichung in die Form gebracht wurde (siehe letzten Post).
Die beiden Ausgaben sind identisch, allerdings ist die letzte gekürzt dargestellt ("x-1" wurde aufgelöst), dass wäre also noch der letzte Schritt der zu tun wäre ...

@JohannisderKaeufer:

Die Idee finde ich auch sehr interessant, werde ich mir gleich mal zu Gemüte führen.

Danke schonmal für eure Hilfe!


----------



## feiste (1. Apr 2011)

Dann wird das aber ganz anders wie bei deinem Beispiel aussehen.



> Zitat: Cru
> 
> allerdings gekürzt ausgerechnet sieht es dann so aus: 3,1429x^3 - 13,7143x^2 + 17,1429x - 4,5714



so wird das NUR aussehen, wenn xi = 0 !!

denn  ( x - xi )³ 
schaut ausgeklammert so aus:

(x-xi)³ = x³ - 3x²*xi + 3x*xi² - xi³ 

wenn jetzt xi = 1  dann würde das so aussehen:

(x - 1)³ = x³ - 3x² + 3x - 1


----------



## Cru (1. Apr 2011)

feiste hat gesagt.:


> wenn jetzt xi = 1  dann würde das so aussehen:
> 
> (x - 1)³ = x³ - 3x² + 3x - 1



Genau. Du vergisst die Variablen in die Rechnung einzubeziehen und diese dann zusammen zu fassen.


----------



## feiste (2. Apr 2011)

@ Cru

du bringst eben die falschen Beispiele.
Bei deinem Beispiel denkt man eben, dass  xi = 0  ist
obwohl du es nicht so haben willst !

Erst nach ein paar mal nachfragen weiß ich was du genau willst.


----------



## muckelzwerg (2. Apr 2011)

Schreib doch bitte mal ein komplettes Beispiel mit einer echten Parabel von Deinen Splines hin.
Bis zur endgültigen Umformung. 
Es ist nicht gerade hilfreich, wenn Du erst das Klammerpolynom als "Lösung" bezeichest und hinterher doch alles komplett ausgerechnet haben willst.
Einige von uns machen sowas vielleicht auf der Arbeit, im Studium oder privat. WIr nehmen uns dann ein bisschen Zeit, schauen uns Dein Problem an und basteln eine Lösung. Und dann erfahren wir, dass Du eigentlich noch was anderes willst. Das ist irgendwie nicht gerade "gut" oder?
Ich hatte extra nochmal nachgefragt, weil es mir nicht ganz klar wurde. 
In der Zeit hätten wir auch was anderes machen (vielleicht auch eine passendere Lösung finden) können. Wenn Du den maximal ausgerechneten Term willst, gibt es vielleicht andere Bibliotheken, die da helfen können.


----------



## Cru (2. Apr 2011)

Ok, mein Fehler, mir ist erst aufgefallen als ich die Daten in der Formel gesehen habe, dass diese ja noch nicht vereinfachht ist.

Ich versuch jetzt mal einen möglichen Lösungsweg zu beschreiben (schon mal sorry für die kryptischen Werte).

Gegeben sind mehre Punkte mit 
	
	
	
	





```
P0(0,0), P1(1,2), P2(2,0), P3(3,2) und P4(4,0)
```
.
Zwischen diesen 5 Punkten werden insgesamt 4 Splines gesucht, die jeweils von dem 1. Punkt zu dem darauf folgenden gehen (z.B. P1->P2).

Die Werte zur Berechnung der Splines werden durch einen Algorithmus in Arrays gespeichert (möchte ich hier nicht weiter drauf eingehen), den Arrays a, b, c und d.

Für das Beispiel P1->P2 sind die Werte: 
	
	
	
	





```
a(2.00), b(0.86), c(4.29), d(3.14)
```
.

Führt man diese Werte in die allgemeine Formel 
	
	
	
	





```
y = (a) + (b*(x - xi)) + (c*((x - xi)^2)) + (d*((x - xi)^3))
```
 ein ist das Resultat: 
	
	
	
	





```
y = 2 + 0.86*(x - 1) + 4.29*((x - 1)^2) + 3.14*((x - 1)^3)
```
. (xi ist immer der erste x-Wert).

Das "Resultat" ist allerdings noch nicht vereinfacht (was mir halt erst viel zu spät aufgefallen ist) und würde ausgerechnet und umgestellt 
	
	
	
	





```
y = 3,14*x^3 - 13,71*x^2 + 17,14*x - 4,57
```
 sein.

Die Daten in die allgemeine Form zu bringen funktioniert (beachtet werden muss dabei, dass bei anderen Beispielen sowohl die x-Werte als auch a, b, c und d sowohl positiv, negativ als auch 0 sein können).

Bis jetzt funktioniert es, dass die Daten in die allgemeine Formel kommen und diese umgestellt wird.


```
public class Formel {

	private String strTeil1, strTeil2, strTeil3, strTeil4, strFormel;

	public Formel(double a, double b, double c, double d, double xi) {

		if (a == 0 && b == 0 && c == 0 && d == 0) {
			strFormel = ("y = 0");
			System.out.println(strFormel);
		} else {
			if (xi == 0) {
				xiIstNull(a, b, c, d);
			} else if (xi < 0) {
				xIstKleinerNull(a, b, c, d, xi);
			} else {
				xIstGroesserNull(a, b, c, d, xi);
			}
		}
	}

	private void xIstGroesserNull(double a, double b, double c, double d,
			double xi) {

		if (d == 0) {
			strTeil1 = "";
		} else {
			strTeil1 = d + "*((x - " + xi + ")^3)";
		}
		if (c == 0) {
			strTeil2 = "";
		} else if (c < 0) {
			strTeil2 = " - " + Math.abs(c) + "*((x - " + xi + ")^2)";
		} else {
			strTeil2 = " + " + c + "*((x - " + xi + ")^2)";
		}
		if (b == 0) {
			strTeil3 = "";
		} else if (b < 0) {
			strTeil3 = " - " + Math.abs(b) + "*(x - " + xi + ")";
		} else {
			strTeil3 = " + " + b + "*(x - " + xi + ")";
		}
		if (a == 0) {
			strTeil4 = "";
		} else if (a < 0) {
			strTeil4 = " - " + Math.abs(a);
		} else {
			strTeil4 = " + " + a;
		}

		strFormel = ("y = " + strTeil1 + strTeil2 + strTeil3 + strTeil4);
		System.out.println(strFormel);

	}

	private void xIstKleinerNull(double a, double b, double c, double d,
			double xi) {

		if (d == 0) {
			strTeil1 = "";
		} else {
			strTeil1 = d + "*((x + " + Math.abs(xi) + ")^3)";
		}
		if (c == 0) {
			strTeil2 = "";
		} else if (c < 0) {
			strTeil2 = " - " + Math.abs(c) + "*((x + " + Math.abs(xi) + ")^2)";
		} else {
			strTeil2 = " + " + c + "*((x + " + Math.abs(xi) + ")^2)";
		}
		if (b == 0) {
			strTeil3 = "";
		} else if (b < 0) {
			strTeil3 = " - " + Math.abs(b) + "*(x + " + Math.abs(xi) + ")";
		} else {
			strTeil3 = " + " + b + "*(x + " + Math.abs(xi) + ")";
		}
		if (a == 0) {
			strTeil4 = "";
		} else if (a < 0) {
			strTeil4 = " - " + Math.abs(a);
		} else {
			strTeil4 = " + " + a;
		}

		strFormel = ("y = " + strTeil1 + strTeil2 + strTeil3 + strTeil4);
		System.out.println(strFormel);

	}

	private void xiIstNull(double a, double b, double c, double d) {

		if (d == 0) {
			strTeil1 = "";
		} else {
			strTeil1 = d + "*x^3";
		}
		if (c == 0) {
			strTeil2 = "";
		} else if (c < 0) {
			strTeil2 = " - " + Math.abs(c) + "*x^2";
		} else {
			strTeil2 = " + " + c + "*x^2";
		}
		if (b == 0) {
			strTeil3 = "";
		} else if (b < 0) {
			strTeil3 = " - " + Math.abs(b) + "*x";
		} else {
			strTeil3 = " + " + b + "*x";
		}
		if (a == 0) {
			strTeil4 = "";
		} else if (a < 0) {
			strTeil4 = " - " + Math.abs(a);
		} else {
			strTeil4 = " + " + a;
		}

		strFormel = ("y = " + strTeil1 + strTeil2 + strTeil3 + strTeil4);
		System.out.println(strFormel);

	}
}public class Formel {

	private String strTeil1, strTeil2, strTeil3, strTeil4, strFormel;

	public Formel(double a, double b, double c, double d, double xi) {

		if (a == 0 && b == 0 && c == 0 && d == 0) {
			strFormel = ("y = 0");
			System.out.println(strFormel);
		} else {
			if (xi == 0) {
				xiIstNull(a, b, c, d);
			} else if (xi < 0) {
				xIstKleinerNull(a, b, c, d, xi);
			} else {
				xIstGroesserNull(a, b, c, d, xi);
			}
		}
	}

	private void xIstGroesserNull(double a, double b, double c, double d,
			double xi) {

		if (d == 0) {
			strTeil1 = "";
		} else {
			strTeil1 = d + "*((x - " + xi + ")^3)";
		}
		if (c == 0) {
			strTeil2 = "";
		} else if (c < 0) {
			strTeil2 = " - " + Math.abs(c) + "*((x - " + xi + ")^2)";
		} else {
			strTeil2 = " + " + c + "*((x - " + xi + ")^2)";
		}
		if (b == 0) {
			strTeil3 = "";
		} else if (b < 0) {
			strTeil3 = " - " + Math.abs(b) + "*(x - " + xi + ")";
		} else {
			strTeil3 = " + " + b + "*(x - " + xi + ")";
		}
		if (a == 0) {
			strTeil4 = "";
		} else if (a < 0) {
			strTeil4 = " - " + Math.abs(a);
		} else {
			strTeil4 = " + " + a;
		}

		strFormel = ("y = " + strTeil1 + strTeil2 + strTeil3 + strTeil4);
		System.out.println(strFormel);

	}

	private void xIstKleinerNull(double a, double b, double c, double d,
			double xi) {

		if (d == 0) {
			strTeil1 = "";
		} else {
			strTeil1 = d + "*((x + " + Math.abs(xi) + ")^3)";
		}
		if (c == 0) {
			strTeil2 = "";
		} else if (c < 0) {
			strTeil2 = " - " + Math.abs(c) + "*((x + " + Math.abs(xi) + ")^2)";
		} else {
			strTeil2 = " + " + c + "*((x + " + Math.abs(xi) + ")^2)";
		}
		if (b == 0) {
			strTeil3 = "";
		} else if (b < 0) {
			strTeil3 = " - " + Math.abs(b) + "*(x + " + Math.abs(xi) + ")";
		} else {
			strTeil3 = " + " + b + "*(x + " + Math.abs(xi) + ")";
		}
		if (a == 0) {
			strTeil4 = "";
		} else if (a < 0) {
			strTeil4 = " - " + Math.abs(a);
		} else {
			strTeil4 = " + " + a;
		}

		strFormel = ("y = " + strTeil1 + strTeil2 + strTeil3 + strTeil4);
		System.out.println(strFormel);

	}

	private void xiIstNull(double a, double b, double c, double d) {

		if (d == 0) {
			strTeil1 = "";
		} else {
			strTeil1 = d + "*x^3";
		}
		if (c == 0) {
			strTeil2 = "";
		} else if (c < 0) {
			strTeil2 = " - " + Math.abs(c) + "*x^2";
		} else {
			strTeil2 = " + " + c + "*x^2";
		}
		if (b == 0) {
			strTeil3 = "";
		} else if (b < 0) {
			strTeil3 = " - " + Math.abs(b) + "*x";
		} else {
			strTeil3 = " + " + b + "*x";
		}
		if (a == 0) {
			strTeil4 = "";
		} else if (a < 0) {
			strTeil4 = " - " + Math.abs(a);
		} else {
			strTeil4 = " + " + a;
		}

		strFormel = ("y = " + strTeil1 + strTeil2 + strTeil3 + strTeil4);
		System.out.println(strFormel);

	}
}
```

Hm jetzt tu sich bei mir die Frage auf, war das jetzt umsonst und man sollte die "Kürzung" vorher durchführen, oder kann man das so nun besser errechnen? Oder kennt jmd vielleicht doch ein Framework, was so etwas lösen kann?

Edit: Auf das Bsp. angewendet ist meine Ausgabe 
	
	
	
	





```
y = 3.14*((x - 1.0)^3) + 4.29*((x - 1.0)^2) + 0.86*(x - 1.0) + 2.0
```


----------



## muckelzwerg (2. Apr 2011)

Ok, klar soweit. Schau Dir mal "JEL" (Java Expressions Library) an. Die habe ich vor einer Weile mal genutzt, um ein paar Termersetzungen zu programmieren. Ich glaube nicht, dass die Lib eine solche Umformung von Haus aus liefert. ABER man kann damit arithmetische Ausdrücke bilden, in denen Java-Objekte, statische Funktionen und Methodenaufrufe enthalten sind.
Ich kann später mal nachschauen, wie ich das damals gemacht habe, wenn Du meinst, dass da was zu holen ist.


----------

