# Polynome



## atomvirus (20. Jan 2011)

Polynome wie z.B p(x) = x^3 + 2x^2 - x + 4 lassen sich durch das array ihrer Koeffizienten darstellen, also im Beispiel {4,-1,2,1}, wobei die zugehörigen Exponenten jeweils implizit durch die Position im array gegeben sind.
Schreiben Sie eine class Polynom mit (mindestens) den Methoden;

public Polynom(double[] coeffs)      // Konstruktor
public double eval(double x)           // Wert an der Stelle x
public int degree()                       // höchster Exponent(Koeffizient !=0)
public void display()                     // Ausgabe in üblicher mathem. Form (s.o.)
public Polynom diff()                    // 1.Ableitung (symbolisch)
public Polynom mul(Polynom p)      // liefert this * p; requires p!=null

__________________________
__________________________

Mein Problem ist momentan der Konstruktor und die Methode eval, mir ist nicht ganz klar wie ich den Konstruktor aufbaue und ihn mit einem Testprogramm durchlaufen kann...

Und wo bzw. in welcher Methode muss ich das Array mit den Exponenten verbinden ?

lg AV


----------



## illuminus (20. Jan 2011)

```
class ...

 double coeffs[];

 public Polynom(double[] coeffs){
     this.coeffs = coeffs;
  }

public double eval(double x){
 double summ = 0;
 for(int i = coeffs.length -1; i >= 0; i-- )
   summ += Math.pow(coeffs[i], coeffs.length - i);
 return summ;
}


public void display(){
 System.out.print("f(x) = ");
 for(int i = coeffs.length -1; i >= 0; i-- )
 System.out.print( coeffs[i] + "^" + coeffs.length - i + " ");
 System.out.println();
}

public Polynom diff(){
 System.out.print("f(x) = ");
 for(int i = coeffs.length -1; i >= 0; i-- )
 System.out.print( coeffs[i] * (coeffs.length - i) + "^" + (coeffs.length - i - 1) + " ");
 System.out.println();
}
```



Rest machst du
... wo ist das denn bitte Schwer ?


----------



## atomvirus (20. Jan 2011)

Danke für die schnelle Antwort... ja bin totaler Anfänger in Java, da kann auch das schon einiges an Probleme bereiten...

summ += Math.pow(coeffs_, coeffs.length - i);  --> was bewirkt das Math.pow ?_


----------



## illuminus (20. Jan 2011)

in Cool: "param1 to the POWer of param2"

Deutsch: param1 hoch param2


----------



## Andi_CH (21. Jan 2011)

So als Hinweis:


```
summ += Math.pow(coeffs[i], coeffs.length - i);
```

Math ist doch unterstrichen - klick mal drauf und suche dann nach pow ....
Die direkte Verlinkung vom Forum zur API-Beschreibung ist doch ein super-feature.


----------



## Gonzo17 (21. Jan 2011)

illuminus hat gesagt.:


> ```
> public double eval(double x){
> double summ = 0;
> for(int i = coeffs.length -1; i >= 0; i-- )
> ...



Das ist ja wohl Quatsch. Du potenzierst den Koeffezienten, aber eigentlich muss der Wert x potenziert werden und der Koeffizient anschließend multipliziert.

Und weshalb du bei der Methode 
	
	
	
	





```
public Polynom diff()
```
 auf die Konsole ausgibst, statt ein Polynom zurückzugeben, verstehe ich auch nicht. Zumal dort mit Sicherheit ein Fehler auftreten wird, da kein return vorhanden ist.


----------



## atomvirus (22. Jan 2011)

...ja Stimmt, der Ansatz von illuminati ist ganz nett, nur nicht richtig... Aber habs schon rausbekommen, trotzdem danke an alle


----------



## illuminus (22. Jan 2011)

illuminus ! So wie "Peanut-Butter" 

Ich hab das ma eben runter gerattert als Denkansatz für den Kleinen. Bin selbst Lehrer und geb nem Schüler doch keine fertigen korrekten Lösungen. An Etwas müssen dies doch lernen


----------



## atomvirus (23. Jan 2011)

Ich fand deinen denkansatz super, wollte keine Kritik an deinen Prog-Kentnissen ausüben...

Habe es jetzt mal ein bisschen daran gearbeitet, nur die Methode Polynom mul(Polynom p) --> liefert this * p macht mir noch probleme, da brauch ich ja nen wirklich guten Algo zum Multiplizieren zweier Polynome ?!

...Hier mal mein Code


```
public class Polynom {
	
	double coeffs[];
	double xclass;
	
	public Polynom(double[] coeffs){ //Kontstruktor
		 this.coeffs = coeffs;
	}
	 
	public double eval(double x){ // Gibt Ergebnis der f(x) 
		double summ = 0;
		double xclass = x;
		
		for(int i = coeffs.length -1; i >= 0; i-- )
			summ = summ + (coeffs[i] * Math.pow(xclass,i));
			return summ;
	}
	 
	 
	public void display(){ // erledigt
		
		System.out.print("f(x) = ");
		
		for(int i = coeffs.length -1; i >= 0; i-- ) {
			
			if(coeffs[i] == 0)     				// Sonderfall wenn Wert = 0
				System.out.print("");
			
			else if (coeffs[i] == 1){			// Sonderfall wenn Wert = 1
				
				if (coeffs[0] == 1)					// und Zahl^0 == 1
					System.out.print(" + 1");
				
				else if (i == coeffs.length -1) 	// und der 1. Wert ist
					System.out.print("x^" + i);
				
				else if(coeffs[i+1] == 0)			// und davor eine 0 steht
					System.out.print("x^" + i);
					
				else								// und sonst keine Sonderfall eintritt 
					System.out.print(" + x^" + i);
					
			}
			
			else if (coeffs[i] > 0){						// Wenn Wert positiv...
				
				if(i == 0){									// und die Potenz == 0
					
					if (i == coeffs.length -1)				// und der 1. Wert ist
						System.out.print(coeffs[i]);
					
					else if(coeffs[i+1] == 0)				// und davor eine Null war
						System.out.print(coeffs[i]);
					
					else 									// und nicht der 1. Wert ist
						System.out.print(" + " + coeffs[i]); 
				}
				else if (i == 1){							// und die Potenz == 1
					
					if (i == coeffs.length -1)				// und der 1. Wert ist
						System.out.print(coeffs[i] + "*x");
					
					else if(coeffs[i+1] == 0)				// und davor eine Null war
						System.out.print(coeffs[i] + "*x");
					
					else									// und nicht der 1. Wert ist
						System.out.print(" + " + coeffs[i] + "*x");
				}
				else if (i > 1){							// und die Potenz < 1 (sprich kein Sonderfall)
					
					if (i == coeffs.length -1)				// und der 1. Wert ist
						System.out.print(coeffs[i] + "x^" + i);
					
					else if(coeffs[i+1] == 0)				// und davor eine Null war
						System.out.print(coeffs[i] + "x^" + i);
					
					else									// und wenn kein sonderfall eintritt
						System.out.print(" + " + coeffs[i] + "x^" + i);
				}
			}
			
			else if (coeffs[i] < 0){		// Wenn Wert negativ...
				if(i == 0)						// und Potenz == 0
					System.out.print(coeffs[i]);
				
				else if (i == 1){					// und Potenz == 1
					System.out.print(coeffs[i] + "*x");
				}
				else if (i < 1){					// und Potenz < 1 (kein Sonderfall)
					System.out.print(coeffs[i] + "x^" + i);
				}
			}
			
			
			else System.out.println("Fehler!");
		}
	}
		public Polynom diff(){
	
		System.out.println();
		System.out.println("1. ableitung");
		
		Polynom polydiff = new Polynom(coeffs);
	
		for (int j = coeffs.length - 1; j >= 1; j--){	// Des wär die Formel wenn i des polydiff wie a normales Array ansprechen 
			polydiff[j-1] = j * coeffs[j];				// könnte, aber funzt nit, obwohl jo polydiff von Polynom-Konstr. kommt und
		}												// des wär ja a array ?! 
		return polydiff;	
	}
		public Polynom mul(Polynom p){
			
		}
}
```


----------



## Gonzo17 (24. Jan 2011)

Zu 
	
	
	
	





```
public Polynom diff()
```
: da hast du etwas noch nicht so richtig verstanden. Die Klasse Polynom selbst ist kein Array, sondern hat ein Attribut 
	
	
	
	





```
double coeffs[]
```
, welches ein Array mit double-Werten ist. Du kannst also ein Objekt vom Typ Polynom nicht als Array ansprechen, sondern muss das Attribut ansprechen. Das sähe dann beispielsweise so aus: 
	
	
	
	





```
polydiff.coeffs[j - 1]
```
.

Zu 
	
	
	
	





```
public Polynom mul(Polynom p)
```
: da solltest du dir überlegen, wie du es machen würdest, wenn du es auf einem Blatt Papier rechnen musst. Schreib dir zwei Polynome auf und versuche diese zu multiplizieren. Du wirst denke ich schon sehen, was getan werden muss. Schreib dir die einzelnen Schritte auf und versuchs zu programmieren. Machs nicht zu kompliziert, grob aufschreiben wird denke ich reichen.


----------



## atomvirus (24. Jan 2011)

Das mit der diff() methode, hab ich schon geändert danke, war noch ne ältere version...

Ja das hab ich schon probiert, nur muss sich ja auch der speicherplatz und alles ändern, das sprengt ja bisschen den rahmen... dachte mir es gibt da einen bestimmten algorithmus zum rechen


----------



## Gonzo17 (24. Jan 2011)

Kann dir ja mal ne kleine Starthilfe geben (weiß ja nicht was du bisher hast).

Generell musst du ja jeden Summanden des einen Polynoms mit jedem des anderen multiplizieren. Den Grad des neuen Polynoms (also des Ergebnisses) erhältst du durch das Multiplizieren der größten Summanden je Polynom. Beispiel: x^y * x^z = x^(y+z). Ist also ganz einfach, du musst nur den Grad beider Polynome addieren und schon hast du den Grad deines neuen Polynoms. Damit ist der Anfang getan, du kannst dir ein Polynom eines bestimmten Grades erstellen und musst dieses "nur" noch füllen. Wobei das ja auch kein großes Problem darstellen sollte, es sind einfach zwei for-Schleifen. Die erste for-Schleife durchläuft das erste Polynom, darin ist eine zweite for-Schleife für das zweite Polynom. Bei jedem Schritt musst du lediglich die Exponenten addieren und die Koeffizienten multiplizieren, das Ergebnis addierst du an die Stelle des neuen Polynoms, an der der neue Exponent liegt. Mehr ist da nicht zu tun.

Tipp: Damit du beim Erstellen eines "leeren" Polynoms vom Grad n nicht so viel Arbeit hast, würde ich dir raten, einfach einen neuen Konstruktor zu erstellen. Jeder Koeffizient sollte da auf 0 initialisiert sein, aber dann hast du wenigstens schonmal ein Array mit passender Größe n. 


```
public Polynom(int degree){
// das musst du selbst rausfinden :)
}
```


----------



## atomvirus (24. Jan 2011)

```
public int degree(){
		
		int expo = 0;
		System.out.print("hoechster Exponent: ");
			for(int i = coeffs.length -1; i > 0; i--) {
			
				if(coeffs[i] != 0){
					expo = i;
					break;
				}	 
			}
		return expo;
```

...das ist meine degree methode, funktionieren tut sie, ob es schön programmiert ist kann ich nicht beurteilen...

hab jetzt an der mul getüffelt aber komm einfach nicht weiter, hab da nen kleinen Hänger...
könntest ma nit an kleinen pseudo code geben, damit ich was visuelles hab, vielleicht wirds mir dann klar, wie ich es programmier technisch umsetzen kann...


----------



## Gonzo17 (24. Jan 2011)

Ja, ist ansich ok. Hast du schon einen Konstruktor gemacht (wie oben vorgeschlagen), der als Parameter den gewünschten Grad des Polynoms annimmt?

Ok, dann hier mal ein Algorithmus in Worten.

```
Gegeben sind die Polynome a, mit Grad g1, und b, mit g2, sowie deren Summanden mit Koeffizienten.

Erzeuge ein neues Polynom vom Grad g1+g2.

Für jeden Summanden s1 von Polynom a tue folgendes
    Für jeden Summanden s2 von Polynom b tue folgendes
        Multipliziere Koeffizient von s1 mit Koeffizient von s2 (Ergebnis ist k)
        Addiere Exponent von s1 mit Exponent von s2 (Ergebnis ist e)
        Addiere k an der Stelle e im neuen Polynom ins Array der Koeffizienten

Rückgabe des neuen Polynoms
```

Da jeder Summand durch Koeffizient und Exponent dargestellt wird bei einem einfachen Polynom, ist das hier ganz einfach zu lösen.


----------



## atomvirus (24. Jan 2011)

Ich glaub ich habe noch ein Grundlegendes Problem, dass ich das mit den Referenzen doch noch nicht ganz verstanden habe...

```
public Polynom diff(){
	
		System.out.println();
		System.out.print("1. ableitung: ");
		
		double[] array = new double[20];
		
		for (int j = coeffs.length - 1; j >= 1; j--){	
			array[j-1] = j * coeffs[j];		
		}
		
		Polynom polydiff = new Polynom(array);
		return polydiff;	
	}
```
...Hier ist es ja so, dass ich zuerst das fertige Array gemacht habe und danach eine neue Referenz?! namens polydiff mache... Was habe ich jetzt eig. damit wirklich in der Hand?

bei mul(Polynom p) muss ich das Polynom p zuerst wieder ein array daraus machen? ...häng gerade mit meinen Gedanken...


----------



## Landei (24. Jan 2011)

[c]new Polynom(array)[/c] legt ein neues Objekt im Speicher an und gibt eine _Referenz_ (nicht das Objekt selber) darauf zurück. Diese Referenz wird einer Variablen namens [c]polydiff[/c] gespeichert. Dasselbe gilt für Arrays: [c]new double[20];[/c] erstellt ein Array-Objekt und liefert dessen Referenz zurück, die in der Variable [c]array[/c] gespeichert wird. Später wird dann einem *Element* des Arrays (über die Referenz mit Index) etwas zugewiesen. Bei Objekt-Arrays gibt es nämlich die Feinheit, dass sie am Anfang leer sind. Ein frisch erzeugtes Array ist sozusagen erst mal ein leerer "Parkplatz"...


Variablen enthalten _niemals_ Objekte, nur Primitve oder Referenzen.



> bei mul(Polynom p) muss ich das Polynom p zuerst wieder ein array daraus machen?


Polynom _ist _kein Array, es_ enthält_ eines. Also kannst du in [c]mul(Polynom p)[/c] auf das Array von [c]p[/c] mit [c]p.coeffs[/c] zugreifen.


----------



## atomvirus (24. Jan 2011)

vielen Danke, das hilft mir wirklich weiter, gut erklärt 

...trotzdem ist mir der Sinn noch nicht klar, wieso es leichter ist, hier einen neuen Konstruktor anzulegen, damit ich mir arbeit erspare?


```
public class Polynom {
	
	double coeffs[];
	double xclass;
	double n;
	double coeffsmul[];
	int g1;
	int g2;
	
	public Polynom(double[] coeffs){ //Kontstruktor
		 this.coeffs = coeffs;
	}
	
	public Polynom(int gges){
		coeffsmul = new double[gges];
		
	}
	public Polynom mul(Polynom p){
		
		g1 = coeffs.length - 1;
		g2 = p.coeffs.length - 1;
		
		Polynom polydiff = new Polynom(g1+g2);
		
	}
```

...hat meine logik bis dahin, einen Sinn, oder bin ich noch immer total am holzweg?


----------



## Gonzo17 (24. Jan 2011)

Du brauchst keine zusätzliche Variable 
	
	
	
	





```
coeffsmul[]
```
, denn egal mit welchem Konstruktor du das Polynom erstellst, es hat ja immer genau n+1 Koeffizienten (einschließlich der 0, falls ein Summand "wegfällt") beim Grad n des Polynoms. Und dann würde ich dir raten jeden Koeffizienten im Array auf 0 zu initialisieren. (Oder wird das bei double automatisch gemacht? Weiß ich nicht, musst du testen bzw vll weiß es jemand) (Edit: Habs schnell getestet, werden tatsächlich automatisch mit 0.0 initialisiert, man muss also nur ein Array der Länge n+1 vom Typ double erstellen)

Der Anfang deiner Methode ist richtig, wobei du ja die Methode 
	
	
	
	





```
public int degree()
```
 schonmal geschrieben hast, also nutze sie doch einfach.


----------



## atomvirus (24. Jan 2011)

> Du brauchst keine zusätzliche Variable
> 
> 
> 
> ...



..also kann ich das so lassen:


```
public Polynom(int gges){
		coeffs = new double[gges];
```

...aber da habe ich ja ein problem bei: 

```
public Polynom mul(Polynom p){
		
		g1 = coeffs.length - 1;
		g2 = p.coeffs.length - 1;
		double k;
		int e;
		
		Polynom polymul = new Polynom(g1+g2);
		
		for(int i = coeffs.length - 1; i >= 0; i--){
			for(int j = p.coeffs.length - 1; j >= 0; j--) {
				k = coeffs[i] * p.coeffs[j];
				e = i + j;
				polymul.coeffs[e] = polymul.coeffs[e] + k;  // ist das zulässig ?
			}
		}
		return polymul;
	}
```

...Die schleifen sist auf dem Vorschlag von Gonzo17, die müssten ja funktionieren...


----------



## Gonzo17 (24. Jan 2011)

atomvirus hat gesagt.:


> ..also kann ich das so lassen:
> 
> 
> ```
> ...



Das ist nicht ganz richtig. Beispiel: ein Polynom vom Grad 2 hat 3 Koeffizienten, nämlich für x^0, x^1 und x^2. Dementsprechenden ist die Anzahl der Koeffizinenten immer um 1 höher als der Grad des Polynoms.


Zulässig ist es, ja, kürzer schreibt man 
	
	
	
	





```
polymul.coeffs[e] += k;
```

Wobei ich ein paar Sachen noch anmerken möchte. Schau mal, du hast g1 und g2 schon festgelegt, wieso verwendest du diese nicht in den for-Schleifen? Und weiterhin hast du, wie ich auch angemerkt hab, bereits ein Methode 
	
	
	
	





```
public int degree()
```
, die dir schon den Grad deines Polynoms liefert, ohne dass du über das Array der Koeffizienten gehen musst. Nutze das doch.


----------



## atomvirus (24. Jan 2011)

> Das ist nicht ganz richtig. Beispiel: ein Polynom vom Grad 2 hat 3 Koeffizienten, nämlich für x^0, x^1 und x^2. Dementsprechenden ist die Anzahl der Koeffizinenten immer um 1 höher als der Grad des Polynoms.



...ja eig. klar, danke...





> ...bereits ein Methode
> 
> 
> 
> ...



...stimmt danke, gibt es einen bestimmten Grund über die Methode degree() zu gehen, anstatt über das array?


...Hab jetzt alles so gut wie fertig, nur gibt mir der Algo bei mul() nicht das richtige raus! 

```
for(int i = g1; i >= 0; i--){
			for(int j = g2; j >= 0; j--) {
				k = coeffs[i] * p.coeffs[j];
				e = i + j;
				System.out.println("k: " + k);
				System.out.println("e: " + e);  
				polymul.coeffs[e] = polymul.coeffs[e] + k;
```

hab mir k & e jeweils ausgeben lassen und das stimmt, wenn man es zusammen rechnent, sprich es muss bei der übergabe irgendetwas falsch laufen...

```
polymul.coeffs[e] = polymul.coeffs[e] + k;
```

...obwohl es meiner meinung nach stimmt...

Testklasse:


```
double[] test1 = {3,-2,0,1};
		double[] p = {2,0,2};
		
		Polynom poly1 = new Polynom(test1);
		Polynom pp = new Polynom(p);
		
		System.out.println("poly1: ");
		
		poly1.display();
		System.out.print(poly1.eval(2));
		poly1.diff().display();
		System.out.println(poly1.degree());
		
		poly1.mul(pp).display();
```

Ergebnis:

poly1: 

poly1: 
 k:2.0 e:5 k:0.0 e:4 k:2.0 e:3 k:0.0 e:4 k:0.0 e:3 k:0.0 e:2 k:-4.0 e:3 k:-0.0 e:2 k:-4.0 e:1 k:6.0 e:2 k:0.0 e:1 k:6.0 e:0f(x) = 2.0x^5 + 6.0x^2-4.0*x + 6.0


----------



## atomvirus (24. Jan 2011)

Zum Schluss: 

Habe die Fehler gefunden und behoben, danke an alle die mir dabei geholfen haben !


----------



## Gonzo17 (25. Jan 2011)

atomvirus hat gesagt.:


> ...stimmt danke, gibt es einen bestimmten Grund über die Methode degree() zu gehen, anstatt über das array?



Bei diesem Beispiel denkt man sich natürlich - braucht man das? Nunja, es sind immerhin 3 Zeilen. Wenn man statt dieser 3 Zeilen immer nur die Methode aufrufen musst, spart man Code. Nimmt man Änderungen vor, muss man das nur an einer Stelle tun (Wartbarkeit des Codes). Will den Code erweitern, muss man nicht erst schauen, wie man es damals (oder jemand anderes) getan hat, sondern ruft einfach die Funktion auf. Ich meine klar, das ist jetzt bei diesem Beispiel alles von untergeordneter Relevanz, aber schon wenn mit Leuten in einem Team arbeitest, dein Projekt mehr als eine Klasse (meistens auch mehr als 10, 20 oder 50 Klassen) hat, dann vereinfacht das die ganze Sache. Du wirst merken, dass du dir dann auch nicht genau jede Stelle merken kannst, man weiß nen Monat später beim Betrachten des Codes vielleicht nicht mehr, warum an dieser Stelle genau das passieren sollte. Und da gehts dann meistens um nicht ganz so triviale Dinge wie Polynome. Deswegen immer sauberen, einfachen und einheitlichen Code produzieren, den man am besten natürlich noch dokumentiert.


----------

