# N*N Matrix Determinante berechnen



## AsterixdGallier (3. Apr 2012)

Hallo ich versuche schon bestimmt 6-7 stunden ein programm zu schreiben, dass mir eine determinante von einer n*n matrix berechnet. 3*3 klappt schon gut auch 4*4 ging bereits. Allerding kriege ich N*N einfach nicht hin.
Mein Code bis jetzt:


```
public class Mathetool {

	public static void main(String[] args) 
	{
		int n = 5;
		
		double [][] matrix = new double[n][n];
		matrix [0][0] = 2;
		matrix [0][1] = 3;
		matrix [0][2] = 3;
		matrix [0][3] = -2;
		matrix [0][4] = 3;

		matrix [1][0] = 3;
		matrix [1][1] = -2;
		matrix [1][2] = 2;
		matrix [1][3] = 4;
		matrix [1][4] = 0;
		
		matrix [2][0] = -2;
		matrix [2][1] = 1;
		matrix [2][2] = 3;
		matrix [2][3] = 0;
		matrix [2][4] = 10;
		
		matrix [3][0] = 4;
		matrix [3][1] = 2;
		matrix [3][2] = 4;
		matrix [3][3] = 5;
		matrix [3][4] = 6;
		
		matrix [4][0] = 1;
		matrix [4][1] = 0;
		matrix [4][2] = 7;
		matrix [4][3] = 2;
		matrix [4][4] = 3;
		
		Mathetool matheTool = new Mathetool();
		matheTool.determinanteAll(n, matrix);
	}
	
	public double determinanteAll(int n, double[][] matrix)
	{
		if (n == 3)
		{
			calculateDeterminante3x3(n, matrix);
		}
		else
		{
			calculateNxN(n, matrix);
		}	
		return n;
	}
	
	public double calculateDeterminante3x3(int n, double[][] matrix)
	{
			double determinante = 0;
			double zwischenErgebnisAddition = 0;
			double zwischenErgebnisSubtrahtion = 0;
			double matrixElement = 1;
			double matrixElement2 = -1;
			int j = 2;
			int k = 0;
			for (int p = 0; p < n; p++)
			{
				matrixElement = 1;
				matrixElement2 = -1;
				for (int i = 0; i < n; i++)
				{
					matrixElement = matrix[k][i] * matrixElement; 
					matrixElement2 = matrix[k][j] * matrixElement2;
					j = j - 1;
					if (j == -1)
					{
						j = n-1;
					}
					k = (k + 1)%n;
				}
				zwischenErgebnisAddition = zwischenErgebnisAddition + matrixElement;
				zwischenErgebnisSubtrahtion = zwischenErgebnisSubtrahtion + matrixElement2;
				determinante = zwischenErgebnisAddition + zwischenErgebnisSubtrahtion;
				k = k + 1;
				System.out.println(determinante);
			}	
		return determinante;
	}
	
	public double calculateNxN(int n, double [][] matrix)
	{
		double[][] matrixHelp = new double [n-1][n-1];
		double wholeDeterminante = 0;
		double ergebnis = 0;
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				int l = 0;
				for (int k = 1; k < n; k++)
				{
					matrixHelp[(j%(n-1))][l] = matrix[(j+i)%n][k];
					l = l + 1;
				}
			}
//			wholeDeterminante = calculateDeterminante3x3(3, matrixHelp) * matrix[i][0];
//			if ((i%2)!=0)
//			{
//				wholeDeterminante = wholeDeterminante * -1;
//			}			
//			System.out.println(matrixHelp[0][n-2]);
			n--;
			
			
			if (n == 3)
			{
				calculateDeterminante3x3(n, matrixHelp);
			}
			else if (n > 3)
			{
				calculateNxN(n, matrixHelp);
			}
			
//			ergebnis = wholeDeterminante + ergebnis;
//			n = n - 1;
//			calculateNxN(n, matrixHelp);
		}
		return ergebnis;
	}
}
```
Vllt denke ich viel zu kompliziert..
Kann mir jemand weiterhelfen??


----------



## nillehammer (3. Apr 2012)

Fachlich blicke ich nicht so durch (Matrizen sind schon etwas länger her bei mir). Dein Code sieht mir aber nach rekursiven Aufrufen aus. Dort, wo Du rekursive Aufrufe machst, musst Du natürlich irgendwas mit dem Rückgabewert der aufgerufenen Methode anfangen.

Und grundsätzlich: Baue Deine Methoden so auf, dass es eine public Methode gibt, die nur einmal aufgerufen wird. Diese ruft dann die rekursiven privaten Methoden mit passenden Parametern auf. Die rekursiven privaten Methoden schreibst Du so, dass Du die Abbruchbedingung für die Rekursion inkl. return-Statement an den Anfang stellst. Danach kommen die rekursiven Aufrufe auch mit einem return-Statement versehen.

Nachfolgender Beispielcode zum einfachen Nachvollziehen:

```
// Der public-Teil, der ein einziges Mal aufgerufen wird und gleich den Parameter validiert
public static int fakultaet(final int value) {
  if (value < 1) {
    throw new IllegalArgumentException("Value darf nicht kleiner 1 sein!");
  }
  return berechneFakultaet(value);
}

// Der private Teil mit geeigneten Returnvalue und Parametern für rekursiven Aufruf. Validierung ist hier
// nicht nötig. Die Methode ist private. Der einzige der sie verwenden kann, bist Du selbst. Du solltest
// in der Lage sein, die Methode mit gültigen Werten aufzurufen.
private static int berechneFakultaet(final int value) {
  // Die Abbruchbedingung mit entspr. Returnstatement
  if (value == 1) {
    return value;
  }

  // Der rekursive Aufruf
  return value * berechneFakultaet(value -1);
}
```


----------



## SlaterB (3. Apr 2012)

im rekursiven Aufruf soll das n kleiner sein, daher grundsätzlich schon ein Weg der nicht in Endlosschleife enden soll,

umgesetzt aber natürlich noch nicht gut, in einer Schleife
>  for (int i = 0; i < n; i++)
kann unmöglich das n verringert werden,
der Rückgabewert des Rekursionsaufruf wird nicht verwendet, das stimmt, einige Zeilen sind auch auskommentiert

es fehlt einfach ne Menge, was soll man da sagen?
andere könnten den Rest dazuprogrammieren, aber naja 

sortiere doch in Ruhe deine Gedanken, 
schaue dir ein Beispiel für 4 bzw. die eingetippen Werte für 5x5 genau an, was ist nach der Herleitung 
Determinante ? Wikipedia
nach Laplacescher Entwicklungssatz (richtig?) im einzelnen zu tun, auf Papier gerechnet?
wie ist das im Programm umzusetzen?

sicherlich kaum durch eine Schleife in der i mal  n--; bis auf 0 ausgeführt wird,
der grundsätzliche Ablauf muss doch mal geklärt werden


----------



## AsterixdGallier (3. Apr 2012)

SlaterB hat gesagt.:


> im rekursiven Aufruf soll das n kleiner sein, daher grundsätzlich schon ein Weg der nicht in Endlosschleife enden soll,
> 
> umgesetzt aber natürlich noch nicht gut, in einer Schleife
> >  for (int i = 0; i < n; i++)
> ...



n wird doch weniger muss jawohl auch, aus 5x5 soll ja schließlich 4x4 und so weiter werden. was noch fehlt ist meiner meinung nach, dass man die unterdeterminanten multipliziert.


----------



## AsterixdGallier (3. Apr 2012)

Dieser Code haut sowohl für 3x3 als auch für 4x4 hin.
Eigentlich ist doch nxn von prinzip her mit 4x4 identisch.
da kann es doch nicht sein dass ich noch viel verändern muss:

```
public class Mathetool {

	public static void main(String[] args) 
	{
		int n = 4;
		
		double [][] matrix = new double[n][n];
		matrix [0][0] = 2;
		matrix [0][1] = 3;
		matrix [0][2] = 3;
		matrix [0][3] = -2;

		matrix [1][0] = 3;
		matrix [1][1] = -2;
		matrix [1][2] = 2;
		matrix [1][3] = 4;
		
		matrix [2][0] = -2;
		matrix [2][1] = 1;
		matrix [2][2] = 3;
		matrix [2][3] = 0;
		
		matrix [3][0] = 4;
		matrix [3][1] = 2;
		matrix [3][2] = 4;
		matrix [3][3] = 5;
		
		Mathetool matheTool = new Mathetool();
		matheTool.determinanteAll(n, matrix);
	}
	
	public double determinanteAll(int n, double[][] matrix)
	{
		if (n == 3)
			{
				calculateDeterminante3x3(n, matrix);
			}
		else
		{
				System.out.println(calculate4x4(n, matrix));
		}
			
		return n;
	}
	
	public double calculateDeterminante3x3(int n, double[][] matrix)
	{
			double determinante = 0;
			double zwischenErgebnisAddition = 0;
			double zwischenErgebnisSubtrahtion = 0;
			double matrixElement = 1;
			double matrixElement2 = -1;
			int j = 2;
			int k = 0;
			for (int p = 0; p < n; p++)
			{
				matrixElement = 1;
				matrixElement2 = -1;
				for (int i = 0; i < n; i++)
				{
					matrixElement = matrix[k][i] * matrixElement; 
//					System.out.println( matrix[k][i]);
					matrixElement2 = matrix[k][j] * matrixElement2;
					j = j - 1;
					if (j == -1)
					{
						j = n-1;
					}
					k = (k + 1)%n;
				}
				zwischenErgebnisAddition = zwischenErgebnisAddition + matrixElement;
//				System.out.println(zwischenErgebnisAddition);
				zwischenErgebnisSubtrahtion = zwischenErgebnisSubtrahtion + matrixElement2;
				determinante = zwischenErgebnisAddition + zwischenErgebnisSubtrahtion;
				k = k + 1;
			}	
//			System.out.println("Determinante: " + determinante);
		return determinante;
	}
	
	public double calculate4x4(int n, double [][] matrix)
	{
		double[][] matrixHelp = new double[4][3];
		double[][] matrixHelp3x3 = new double [3][3];
		double wholeDeterminante = 0;
		double ergebnis = 0;
		for (int i = 0; i < 4; i++)
		{
			for (int j = 0; j < n; j++)
			{
				int l = 0;
//				System.out.println("");
				for (int k = 1; k < n; k++)
				{
//						System.out.println(matrix[j][k]);
						matrixHelp3x3[(j)%3][l] = matrix[(j+i)%4][k];
//						System.out.println(matrixHelp[j][l]);
//						matrixHelp3x3[(j+i)%3][l] = matrixHelp[j][l];
//						System.out.println(matrixHelp3x3[0][2]);
//						System.out.println(matrixHelp3x3[2][2]);
//						matrixHelp[j][k-1] = matrix[((j+(i+1))%4)][k];
//						System.out.println(matrix[((j+(i+1))%4)][k]);
//						calculateDeterminante3x3(3, matrixHelp3x3);
//						System.out.println(matrixHelp3x3[0][0]);
						l = l + 1;
						
				}
			}
//			double determinante = 0;
//			for (int o = 0; o < n; o++)
//			{
//				determinante =  matrix[3][0] * calculateDeterminante3x3(3, matrixHelp3x3);
			wholeDeterminante = calculateDeterminante3x3(3, matrixHelp3x3) * matrix[i][0];
			if ((i%2)!=0)
			{
				wholeDeterminante = wholeDeterminante * -1;
			}
//			}
			
			ergebnis = wholeDeterminante + ergebnis;
//			System.out.println(matrixHelp3x3[2][0]);
//			System.out.println("");
		}
//		System.out.println(ergebnis);
//		calculateDeterminante3x3(3, matrixHelp3x3);
//		System.out.println(matrixHelp[3][2]);
//		calculateDeterminante3x3(n, matrixHelp);
		return ergebnis;
	}
}
```
habe es schon versucht allgemein zu halten


----------



## SlaterB (3. Apr 2012)

du brauchst mehrere 4x4-Determinanten, aber innerhalb des ersten Aufrufs muss n nie auf 3 sinken oder darunter,
dass jeder 4x4-Aufruf selber nach 3x3 geht, das erledigt schon die Rekursion, darum musst du dich im ersten Aufruf nicht kümmern,

die Multiplikation fehlt, in der Tat, aber was soll man da sagen? die Formel ist doch bekannt oder nachschlagbar,
der Rückgabewert des rekursiven Aufrufs muss mit irgendeinem Matrix-Wert multipliziert und dann addiert werden usw.,
das kannst du doch in Ruhe im Detail schaffen, was soll man von außen dazu sagen?
die richtige Codezeile könnte ich dir nur nennen wenn ich das ganze praktisch selber komplett programmiere

also schreibe dir mal sauber auf, wie 5x5 aufgeteilt wird, in wieviel Untermatrixen,
Untermethoden helfen auch, dann hast du vielleicht nicht so viele Schleifen,
der Hauptaufbau könnte so sein


```
calculate(n,matrix nn) { // 5
   int nKleiner // 4, einmal reicht, alles andere < n interessiert nicht
   double sum;   
   for ( 0-5) { // eine Schleife reicht
     matrix nknk // ohne Schleife durch Methodenaufruf einer Hilfsmethode (nicht Rekursion!) 
          // die aktuell benötigte Untermatrix bestimmten, in der Untermethode Doppelschleife oder so
     sum += ein Matrix-Wert * rekursiverAufruf(nKleiner,nknk);
   }
   return sum ;
}
```
die Unterscheidung ob 3x3-Methode aufzurufen ist könnte an den Anfang der calculate-Methode,
muss nicht beim rekursiven Aufruf sein,
dann funktioniert das auch falls die Methode initial mit 3 aufgerufen wird,

der int-Parameter könnte auch ganz weg, aus der Matrix kann man die Länge ja ablesen


----------



## AsterixdGallier (3. Apr 2012)

In meinem letzten Code den ich gepostet habe wandle ich doch eine 4er Matrix in 4 3er Matritzen um. Und es funktioniert!
Wenn ich jetzt meine 5er Matrix in 4 4er umwandle, und diese 4 4er jeweils in 4 3er, müsste es doch klappen, und dem code müsste ich dann schon sehr nahe sein oder nicht?


----------



## SlaterB (3. Apr 2012)

oh ja, da habe ich mal ein Posting übersehen, das von 15:48 sieht zuversichtlich aus,

eine Frage besteht aktuell sonst nicht oder?
na dann spätestens jetzt an der nxn-Variante weiterarbeiten, falls das dein Ziel ist


----------



## AsterixdGallier (4. Apr 2012)

Hi ich bins nochmal habe den code weitergemacht, bzw verändert. 


```
public class Mathetool {
	int zähl = 0;
	double result = 0;
	double multiplikator = 1;
	public static void main(String[] args) 
	{
		int n = 4;
		
		double [][] matrix = new double[n][n];
		matrix [0][0] = 1;
		matrix [0][1] = -2;
		matrix [0][2] = 2;
		matrix [0][3] = 3;
//		matrix [0][4] = 3;
//		matrix [0][5] = 11;

		matrix [1][0] = 4;
		matrix [1][1] = 3;
		matrix [1][2] = 1;
		matrix [1][3] = -1;
//		matrix [1][4] = 0;
//		matrix [1][5] = 6;
		
		matrix [2][0] = 5;
		matrix [2][1] = -1;
		matrix [2][2] = 1;
		matrix [2][3] = 2;
//		matrix [2][4] = 7;
//		matrix [2][5] = 1;
		
		matrix [3][0] = -1;
		matrix [3][1] = 0;
		matrix [3][2] = 0;
		matrix [3][3] = 1;
//		matrix [3][4] = 6;
//		matrix [3][5] = 5;
		
//		matrix [4][0] = 1;
//		matrix [4][1] = 10;
//		matrix [4][2] = 3;
//		matrix [4][3] = 4;
//		matrix [4][4] = 3;
//		matrix [4][5] = 10;
		
//		matrix [5][0] = 1;
//		matrix [5][1] = 12;
//		matrix [5][2] = 14;
//		matrix [5][3] = 1;
//		matrix [5][4] = 2;
//		matrix [5][5] = 6;
		
		Mathetool matheTool = new Mathetool();
		matheTool.determinanteAll(n, matrix);
	}
	
	public double determinanteAll(int n, double[][] matrix)
	{
		if (n == 3)
			{
				calculateDeterminante3x3(n, matrix);
			}
//		else if (n == 4)
//		{
//				System.out.println(calculate4x4(n, matrix));
//		}
		else if (n > 3)
		{
			macheNxNEineDimensionKleinerX(n, matrix);
//			System.out.println(result);
		}
			
		return n;
	}
	
	public double calculateDeterminante3x3(int n, double[][] matrix)
	{
			double determinante = 0;
			double zwischenErgebnisAddition = 0;
			double zwischenErgebnisSubtrahtion = 0;
			double matrixElement = 1;
			double matrixElement2 = -1;
			int j = 2;
			int k = 0;
			for (int p = 0; p < n; p++)
			{
				matrixElement = 1;
				matrixElement2 = -1;
				for (int i = 0; i < n; i++)
				{
					matrixElement = matrix[k][i] * matrixElement; 
//					System.out.println( matrix[k][i]);
					matrixElement2 = matrix[k][j] * matrixElement2;
					j = j - 1;
					if (j == -1)
					{
						j = n-1;
					}
					k = (k + 1)%n;
				}
				zwischenErgebnisAddition = zwischenErgebnisAddition + matrixElement;
//				System.out.println(zwischenErgebnisAddition);
				zwischenErgebnisSubtrahtion = zwischenErgebnisSubtrahtion + matrixElement2;
				determinante = zwischenErgebnisAddition + zwischenErgebnisSubtrahtion;
				k = k + 1;
			}	
//			System.out.println("Determinante: " + determinante);
		return determinante;
	}
	

	
	public void macheNxNEineDimensionKleinerX(int n, double [][] matrix) // Macht eine NxN-Matrix zu N (N-1)x(N-1) Matritzen.
	{
		double ergebnis = 0;
		double multiplikator = 2;
		double determinante = 0;
		double zwischenResult = 0;
		double[][] matrixHelp = new double[n-1][n-1];
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
				{
					matrixHelp[(j+(n-2))%(n-1)][((k+(n-2))%(n-1))] = matrix[(j+i)%n][k];
				}
			}
			if (n == 3)
			{
				zwischenResult = calculateDeterminante3x3(n, matrix);
//				computeResult (zwischenResult, 1.0);
			}
			else if (n > 3)
			{
				macheNxNEineDimensionKleinerX((n-1), matrixHelp);
			}
		}
		System.out.println(zwischenResult);
	}
	
//	public void computeResult (double determinante, double multiplicator)
//	{
//		result += determinante * multiplicator;
//	}
	}
```

Sorry für den ganzen auskommentierten kram.
er gibt mir jetzt von beliebigen matritzen alle ergebnisse der untermatritzen aus. also wenn man von 5x5 auf 4x4 auf 3x3 geht. kriege dann also bei einer 4x4 matrix 4 ergebnisse. Eine 4x4 ist ja das gleiche wie 4 3x3 matritzen. Es fehlt nur noch die multiplikation. ich muss die unterdeterminanten ja noch multiplizieren. weiß aber nicht wie das gehen soll, weil mein code rekursiv ist und der wert aus der matritze immer wieder überschrieben wird!
Bin glaube ich nicht mehr weit entfernt vom ziel hat jemand nen guten hinweis??
Er gibt jetzt aktuell 4, 0, -8, -4, 0 aus. (das sind die 4 ergebnisse von den 4 unterdeterminanten der 4x4 matrix) soweit richtig nur die letzte 0 ist überflüssig wie könnte ich die weglassen?


----------



## SlaterB (4. Apr 2012)

macheNxNEineDimensionKleinerX() muss wie calculateDeterminante3x3() einen double zurückgeben,

in der Schleife erhälst du von der einen oder der anderen Mehode einen double, dass ist die Determinante X der jeweiligen Untermatrix,
dieses X musst du ganz nach Formel mit aij multiplizieren, keine Ahnung ob du 'nach der 0-ten Spalte oder 0-ten Zeile entwickelst',
außerdem noch mit -1^(i+j) multiplizieren, auch eben ganz nach Formel, auf dem Papier siehst du ja welche Werte es im Beispiel sein müssen,
der Schleifen-Index spielt eine Rolle und die gewählte Spalte oder Zeile,

alle diese Produkte der Schleife noch aufaddieren, ganz nach Formel (  ) und das ist der Rückgabewert der Methode macheNxNEineDimensionKleinerX(), das ist die entwickelte Determinante


----------



## AsterixdGallier (4. Apr 2012)

SlaterB hat gesagt.:


> macheNxNEineDimensionKleinerX() muss wie calculateDeterminante3x3() einen double zurückgeben,
> 
> in der Schleife erhälst du von der einen oder der anderen Mehode einen double, dass ist die Determinante X der jeweiligen Untermatrix,
> dieses X musst du ganz nach Formel mit aij multiplizieren, keine Ahnung ob du 'nach der 0-ten Spalte oder 0-ten Zeile entwickelst',
> ...



danke, das es double werden muss ist mir klar, habe es nur noch nicht eingetragen.
das problem ist ich kriege den wert mit dem ich multiplizieren muss einfach nicht zu fassen.
ich weiß nicht wie ich den ansprechen soll. es müssten quasi die oberen werte der spalte sein, die ausgelassen wurde. 
also irgendwie sowas wie matrix_[0]. aber so bekomme ich sie leider nicht, weil die matrix durch die rekursion immer wieder mit der neuen kleineren überschrieben wird. und dann nimmt er halt von der kleineren matrix[0], er müsste aber dort nachwievor den von der ersten nehmen..
Man könnte als erste Frage formulieren, wie schaffe ich es dass mir die multiplikatoren einfach nur ausgegeben werden innerhalb meiner methode macheNxNEineDimensionKleinerX. dann brauch ich ja wie du schon gesagt hast nur noch multiplizieren nach der formel ich denke das kriege ich dann hin._


----------



## SlaterB (4. Apr 2012)

du musst jede Stufe für sich betrachten

wenn eine 5x5-Matrix in die Methode reinkommt, dann arbeitest du (per Schleife öfters) in Zeile 123-129 5x daran eine Untermatrix 4x4 Y zu erstellen,
zu dieser Untermatrix Y wird eine Unterdeterminante X berechnet (wie ist dir vollkommen egal, rekursiver Aufruf, fertig ist der Lack)
wenn dieser double-Wert X fertig da ist, bist du wieder dort wo die Untermatrix berechnet wurde,
bzw. in der aktuellen Betrachtung unter Auslassung der Rekursion die ganze Zeit in der 5x5er Bearbeitung,

dort wo du die Untermatrix Y 4x4 berechnet hast, und nun X von Unteraufrufen erhalten hast,
ist der Parameter matrix, die 5x5-Matrix, doch nach wie vor, die ganze Zeit vorhanden, 
ganz simplel kannst du mit matrix_[0] rechnen oder was immer nötig ist

-----

wenn der rekursive Aufruf für eine der 4x4-Matrixen selber zu einem kompletten macheNxNEineDimensionKleinerX()-Ablauf führt,
dann ist 
1. die ursprüngliche 5x5-Matrix nicht nötig, der eigenständige Unter-Ablauf hat seine 4x4-Matrix als eigenen matrix-Parameter,
von dem wiederum 3x3 Untermatrixen Y berechnet und matrix[0] usw. abgefragt werden können
2. diese Unterberechnungen laufen auch völlig getrennt vom ersten und einzigen 5x5-Aufruf, der solange pausiert wird, 
dessen Parameter, Schleifen usw. werden auf keine Weise gestört, 
wenn ein Unteraufruf fertig ist geht dort alles in geordenten Bahnen mit den dortigen Variablen weiter

-> zusammen: es läuft alles_


----------



## AsterixdGallier (5. Apr 2012)

SlaterB hat gesagt.:


> du musst jede Stufe für sich betrachten
> 
> wenn eine 5x5-Matrix in die Methode reinkommt, dann arbeitest du (per Schleife öfters) in Zeile 123-129 5x daran eine Untermatrix 4x4 Y zu erstellen,
> zu dieser Untermatrix Y wird eine Unterdeterminante X berechnet (wie ist dir vollkommen egal, rekursiver Aufruf, fertig ist der Lack)
> ...



ja aber ich glaube du vergisst, dass man zu der untermatrix Y nicht so einfach eine determinante berechnen kann. Aus Y müsste man jetzt wieder 3 3er Matritzen erstellen und diese mit matrix_[0] von Y multiplizieren._


----------



## SlaterB (5. Apr 2012)

die Rekursion ist auf der Welt aus einem einzigen Grunde, nämlich um GENAU 'so einfach [.. etwas zu] berechnen' 

du musst dir darum keine Gedanken machen, der rekursive Aufruf errechnet die Determinante und nur in der aktuellen Schicht muss alles klappen,

denke an eine Menschenkette für Wassereimer oder ein Navi auf dem Weg über tausend Kreuzungen,
jeder einzelne muss nur seine Arbeit korrekt machen, seinen Eimer in die richtige Richtung weiterreichen, an der aktuellen Kreuzung richtig abbiegen,
über vorherige oder spätere Stationen muss man nicht (gleichzeitig) nachdenken, 
das funktioniert (bei geeigneten Aufbau) durch die Gesamtkonstruktion


----------



## AsterixdGallier (5. Apr 2012)

Hi gucke mal hier so siehts grade aus:


```
public double macheNxNEineDimensionKleinerX(int n, double [][] matrix) // Macht eine NxN-Matrix zu N (N-1)x(N-1) Matritzen.
	{
		double ergebnis = 0;
		double multiplikator = 2;
		double determinante = 0;
		double zwischenResult = 0;
		double[][] matrixHelp = new double[n-1][n-1];
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
				{
					matrixHelp[(j+(n-2))%(n-1)][((k+(n-2))%(n-1))] = matrix[(j+i)%n][k];
				}
			}
			if (n == 3)
			{
				zwischenResult = calculateDeterminante3x3(n, matrix);
//				System.out.println(zwischenResult);
//				System.out.println(matrix[i][0]);
//				computeResult (zwischenResult, 1.0);
			}
			else if (n > 3)
			{
				zwischenResult = macheNxNEineDimensionKleinerX((n-1), matrixHelp);
//				zwischenResult = zwischenResult * matrix[i][0];
				System.out.println(matrix[i][0]*zwischenResult);
//				System.out.println(zwischenResult);
//				System.out.println(matrix[i][0]);
			}
			
//			System.out.println(zwischenResult * matrix[i][0]);
		}
		
//		for (int w = 0; w < n; w++)
//		{
//			System.out.println(matrix[w][0]);
//		}
//		System.out.println(zwischenResult);
		return zwischenResult;
	}
```
Wenn ich dort also um else if Zweig das ganze ausgebe kommen die richtig multiplizierten zwischenergebnisse raus. nur dort kann ich sie nicht weiterverwenden weil sie ja danach wieder überschrieben werden..


----------



## SlaterB (5. Apr 2012)

dass du in der Schleife unterscheidest habe ich schon früher als unnötig kompliziert genannt, aber ist zu behandeln

```
for { 
   ...  matrix erstellen

   double zwischenResult = 0; // erst hier deklarieren, macht weniger Probleme
   if (3er) {
       zwischenResult  = calc3er();
   } else {
       zwischenResult  = calcNer();
   }
   // hier die Unterdeterminante in zwischenResult fertig
}
```

kürzer wäre 

```
for { 
   ...  matrix erstellen

   double zwischenResult = calcNer();
   // hier die Unterdeterminante in zwischenResult fertig
}
```
und erst im nächsten Rekursionsschritt, also zu Beginn der Methoe prüfen ob die Dimension 3 ist und dann erst auf calc3er() weiterleiten

----------

jedenfalls sorgt all das nur dafür, dass in der Schleife eine Unterdeterminante X berechnet wird, X = zwischenResult,

jetzt wie ich es gesagt habe und wie du teilweise schon eingebaut hast, jedes dieser X mit z.B. matrix_[0] multiplizieren
und das ganze aufsummieren,
das ist doch eine einfache Aufgabe,
die Variable zwischenResult brauchst du nicht nach der Schleife, bzw. vielleicht schon, irgendeine Variable ja immer,
nimm meinetwegen zwischenResult zur Summierung,
aber dann speichere nicht die Unterdeterminanten X daran, sondern verwende eine separate Variable, das ist doch nun wirklich nicht schwer?



		Java:In die Zwischenablage kopieren


double zwischenResult = 0;
for { 
   ...  matrix erstellen

   double x = .. Unterderminante berechnen;

   zwischenResult += x * matrix[i][0];
}
// hier nun ist zwischenResult das richtige Endergebnis

_


----------



## AsterixdGallier (5. Apr 2012)

So funktinierts jetzt mal wieder für 4x4, aber nxn irgendwie nicht.. versteh nicht mehr warum..???:L


```
public double macheNxNEineDimensionKleinerX(int n, double [][] matrix) // Macht eine NxN-Matrix zu N (N-1)x(N-1) Matritzen.
	{
		double ergebnis = 0;
		double multiplikator = 2;
		double determinante = 0;
		double zwischenResult = 0;
		double[][] matrixHelp = new double[n-1][n-1];
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
				{
					matrixHelp[(j+(n-2))%(n-1)][((k+(n-2))%(n-1))] = matrix[(j+i)%n][k];
				}
			}
			if (n == 3)
			{
				zwischenResult = calculateDeterminante3x3(n, matrix);
//				System.out.println(zwischenResult);
//				System.out.println(matrix[i][0]);
//				computeResult (zwischenResult, 1.0);
			}
			else if (n > 3)
			{
				zwischenResult = macheNxNEineDimensionKleinerX((n-1), matrixHelp);
				zwischenResult = zwischenResult * matrix[i][0];
//				System.out.println(zwischenResult);
				if ((i%2)!=0)
				{
					finale = finale - zwischenResult;
				}	
				else if (i%2==0)
				{
					finale = finale + zwischenResult;
				}

//				System.out.println(finale);
//				System.out.println(matrix[i][0]);
			}
			
//			System.out.println(zwischenResult * matrix[i][0]);
		}
		
//		for (int w = 0; w < n; w++)
//		{
//			System.out.println(matrix[w][0]);
//		}
		System.out.println(finale);
		return zwischenResult;
	}
```


----------



## AsterixdGallier (5. Apr 2012)

SlaterB hat gesagt.:


> dass du in der Schleife unterscheidest habe ich schon früher als unnötig kompliziert genannt, aber ist zu behandeln
> 
> ```
> for {
> ...


_
habs jetzt erst gesehen, aber wieso funktniert der aktuelle code nicht für sachen größer als 4x4. der macht doch alles nach der formel und summiert es nach ein ander auf._


----------



## AsterixdGallier (5. Apr 2012)

Ich kriege einfach die berechnetetn untermatritzen nicht aus der methode raus nach oben hier:

```
public double macheNxNEineDimensionKleinerX(int n, double [][] matrix) // Macht eine NxN-Matrix zu N (N-1)x(N-1) Matritzen.
	{
		double ergebnis = 0;
		double multiplikator = 2;
		double determinante = 0;
		double zwischenResult = 0;
		double[][] matrixHelp = new double[n-1][n-1];
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
				{
					matrixHelp[(j+(n-2))%(n-1)][((k+(n-2))%(n-1))] = matrix[(j+i)%n][k];
				}
			}
			if (n == 3)
			{
				zwischenResult = calculateDeterminante3x3(n, matrix);
//				System.out.println(zwischenResult);
//				System.out.println(matrix[i][0]);
//				computeResult (zwischenResult, 1.0);
			}
			else if (n > 3)
			{
				zwischenResult = macheNxNEineDimensionKleinerX((n-1), matrixHelp);
				zwischenResult = zwischenResult * matrix[i][0];
				System.out.println(zwischenResult);
//				System.out.println(zwischenResult);
//				System.out.println(matrix[i][0]);
			}
			
//			System.out.println(zwischenResult * matrix[i][0]);
		}
		
//		for (int w = 0; w < n; w++)
//		{
//			System.out.println(matrix[w][0]);
//		}
//		System.out.println(zwischenResult);
		return zwischenResult;
	}
```
ich müsste ja 4 werte zurück geben um sie oben dann alle zu multilpizieren, deswegen wollte ich das schon in der methode machen!


----------



## SlaterB (5. Apr 2012)

immer auf Papier ausrechnen, welche Untermatrixen Y zu einem Beispiel rauskommen, 
welche Unterdeterminanten X dazu die Zwischenergebnisse sind, 
welche Multiplikatoren dazu gehören (vielleicht irrst du dich mit matrix_[0], vielleicht ist es matrix[0]),
einfach jeden einzelnen Schritt der Rechnungf kennen und nacheinander im Programmablauf abhaken

solange du selber nicht weißt was zu rechnen ist, ist es reiner Zufall ob du die richtigen oder falschen Formeln umsetzt

wenn du es aber weißt, ist es reiner Fleiß, das im Programm zu vergleichen und so den Fehler einzugrenzen

-----

ich selber kann im Moment nur feststellen, dass augenscheinlich alle Bestandteile vorhanden sind,
ob richtig oder falsch, dazu müsste ich alles selber genauso machen, angefangen mit Zurechtlegen einer Matrix und Ausrechnen auf Papier

-----

> ich müsste ja 4 werte zurück geben um sie oben dann alle zu multilpizieren, deswegen wollte ich das schon in der methode machen! 

nein.., jeder Methodenaufruf gibt genau einen Wert zurück, klappt auch, aber das ist ne Nebendiskussion_


----------



## AsterixdGallier (5. Apr 2012)

SlaterB hat gesagt.:


> immer auf Papier ausrechnen, welche Untermatrixen Y zu einem Beispiel rauskommen, welter Unterdeterminanten X dazu die Zwischenergebnisse sind, welche Multiplikatoren dazu gehören (vielleicht irrst du dich mit matrix_[0], vielleicht ist es matrix[0]),
> einfach jeden einzelnen Schritt der Rechnung, jeden Schriff kennen und nacheinander im Programmablauf abhaken
> 
> solange du selber nicht weißt was zu rechnen ist, ist es reiner Zufall ob du die richtigen oder falschen Formeln umsetzt
> ...


_

danke meine untermatritzen sind richtig, und wie gesagt die ausgabe stimmt auch in der console. mein einziges problem ist es, die ausgegebenen werte zusammen zu rechnen und zurück zugeben.


		Java:In die Zwischenablage kopieren


public class Mathetool {
	int zähl = 0;
	double result = 0;
	double multiplikator = 1;
	double finale = 0;
	public static void main(String[] args) 
	{
		int n = 4;
		
		double [][] matrix = new double[n][n];
		matrix [0][0] = 1;
		matrix [0][1] = -2;
		matrix [0][2] = 2;
		matrix [0][3] = 3;
//		matrix [0][4] = 3;
//		matrix [0][5] = 11;

		matrix [1][0] = 4;
		matrix [1][1] = 3;
		matrix [1][2] = 1;
		matrix [1][3] = -1;
//		matrix [1][4] = 0;
//		matrix [1][5] = 6;
		
		matrix [2][0] = 5;
		matrix [2][1] = -1;
		matrix [2][2] = 1;
		matrix [2][3] = 2;
//		matrix [2][4] = 7;
//		matrix [2][5] = 1;
		
		matrix [3][0] = -1;
		matrix [3][1] = 0;
		matrix [3][2] = 0;
		matrix [3][3] = 1;
//		matrix [3][4] = 6;
//		matrix [3][5] = 5;
		
//		matrix [4][0] = 1;
//		matrix [4][1] = 10;
//		matrix [4][2] = 3;
//		matrix [4][3] = 4;
//		matrix [4][4] = 3;
//		matrix [4][5] = 10;
		
//		matrix [5][0] = 1;
//		matrix [5][1] = 12;
//		matrix [5][2] = 14;
//		matrix [5][3] = 1;
//		matrix [5][4] = 2;
//		matrix [5][5] = 6;
		
		Mathetool matheTool = new Mathetool();
		matheTool.determinanteAll(n, matrix);
	}
	
	public double determinanteAll(int n, double[][] matrix)
	{
		if (n == 3)
			{
				calculateDeterminante3x3(n, matrix);
			}
//		else if (n == 4)
//		{
//				System.out.println(calculate4x4(n, matrix));
//		}
		else if (n > 3)
		{
			macheNxNEineDimensionKleinerX(n, matrix);
//			System.out.println(result);
		}
			
		return n;
	}
	
	public double calculateDeterminante3x3(int n, double[][] matrix)
	{
			double determinante = 0;
			double zwischenErgebnisAddition = 0;
			double zwischenErgebnisSubtrahtion = 0;
			double matrixElement = 1;
			double matrixElement2 = -1;
			int j = 2;
			int k = 0;
			for (int p = 0; p < n; p++)
			{
				matrixElement = 1;
				matrixElement2 = -1;
				for (int i = 0; i < n; i++)
				{
					matrixElement = matrix[k][i] * matrixElement; 
//					System.out.println( matrix[k][i]);
					matrixElement2 = matrix[k][j] * matrixElement2;
					j = j - 1;
					if (j == -1)
					{
						j = n-1;
					}
					k = (k + 1)%n;
				}
				zwischenErgebnisAddition = zwischenErgebnisAddition + matrixElement;
//				System.out.println(zwischenErgebnisAddition);
				zwischenErgebnisSubtrahtion = zwischenErgebnisSubtrahtion + matrixElement2;
				determinante = zwischenErgebnisAddition + zwischenErgebnisSubtrahtion;
				k = k + 1;
			}	
//			System.out.println("Determinante: " + determinante);
		return determinante;
	}
	
//	public double calculate4x4(int n, double [][] matrix)
//	{
//		double[][] matrixHelp = new double[4][3];
//		double[][] matrixHelp3x3 = new double [3][3];
//		double wholeDeterminante = 0;
//		double ergebnis = 0;
//		for (int i = 0; i < 4; i++)
//		{
//			for (int j = 0; j < n; j++)
//			{
//				int l = 0;
//				for (int k = 1; k < n; k++)
//				{
//						matrixHelp3x3[(j)%3][l] = matrix[(j+i)%4][k];
//						l = l + 1;			
//				}
//			}
//			wholeDeterminante = calculateDeterminante3x3(3, matrixHelp3x3) * matrix[i][0];
//			if ((i%2)!=0)
//			{
//				wholeDeterminante = wholeDeterminante * -1;
//			}		
//			ergebnis = wholeDeterminante + ergebnis;
//		}
//		return ergebnis;
//	}
	
//	public void macheNxNEineDimensionKleiner(int n, double [][] matrix) // Macht eine NxN-Matrix zu N (N-1)x(N-1) Matritzen.
//	{
//		double[][] matrixHelp = new double[n][n-1];
//		for (int i = 0; i < n-1; i++)
//		{
//			for (int j = 0; j < n; j++)
//			{
//				for (int k = 0; k < n; k++)
//				{
//					matrixHelp[(j+(n-2))%(n)][((k+(n-2))%(n-1))] = matrix[(j+i)%n][k];
//				}
////				System.out.println(matrixHelp[4][3]);
//			}
//			
//			System.out.println(matrixHelp[4][0]);
//		}
//	}
	
	public double macheNxNEineDimensionKleinerX(int n, double [][] matrix) // Macht eine NxN-Matrix zu N (N-1)x(N-1) Matritzen.
	{
		double ergebnis = 0;
		double multiplikator = 2;
		double determinante = 0;
		double zwischenResult = 0;
		double[][] matrixHelp = new double[n-1][n-1];
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
				{
					matrixHelp[(j+(n-2))%(n-1)][((k+(n-2))%(n-1))] = matrix[(j+i)%n][k];
				}
			}
			if (n == 3)
			{
				zwischenResult = calculateDeterminante3x3(n, matrix);
//				System.out.println(zwischenResult);
//				System.out.println(matrix[i][0]);
//				computeResult (zwischenResult, 1.0);
			}
			else if (n > 3)
			{
				zwischenResult = macheNxNEineDimensionKleinerX((n-1), matrixHelp);
				zwischenResult = zwischenResult * matrix[i][0];
//				System.out.println(zwischenResult);			// DAS HIER IST RICHTIG!!! WIE KRIEGE ICH DIESE WERTE NACH OBEN (VON MIR AUS AUCH SCHON ZUM ERGEBNIS ADDIERT)
//				System.out.println(matrix[i][0]);			// AUCH DIE RICHIGEN FAKTOREN!!
			}
			
//			System.out.println(zwischenResult * matrix[i][0]);
		}
		
//		for (int w = 0; w < n; w++)
//		{
//			System.out.println(matrix[w][0]);
//		}
//		System.out.println(zwischenResult);				// HIER SIND DIE WERTE WIEDER FALSCH PLÖTZLICH, ES KOMMEN WIEDER DIE WERTE HERAUS BEVOR SIE MULTIPLIZIERT WURDEN
		return zwischenResult;
	}
	
//	public void computeResult (double determinante, double multiplicator)
//	{
//		result += determinante * multiplicator;
//	}
	}

Habe jetzt als Kommentar geschrieben was ich wo meine._


----------



## SlaterB (5. Apr 2012)

hmm, das ist ja dann doch wieder der einfache Punkt, ich dachte den hättest du nach meinen letzten Erläuterungen richtig,
habe nicht genau genug geschaut,
in zwischenResult speicherst du immer nur den aktuellen Wert pro Schleifendurchlauf,

all diese Werte musst du addieren, das ist doch die sehr billig nach so komplexen anderen Themen?
definiere dir vor der Schleife eine weitere Variable, meinetwegen 'sum',
und in der Schleife einfach nur sum += zwischenResult;
schon hast du alle ZwischenResulte zusammen, was das Endergebnis ist?!


----------



## AsterixdGallier (5. Apr 2012)

SlaterB hat gesagt.:


> hmm, das ist ja dann doch wieder der einfache Punkt, ich dachte den hättest du nach meinen letzten Erläuterungen richtig,
> habe nicht genau genug geschaut,
> in zwischenResult speicherst du immer nur den aktuellen Wert pro Schleifendurchlauf,
> 
> ...



Jo danke das habe ich jetzt gemacht, und das klappt auch bei 4X4. Aber nicht mehr bei 5X5 
Habe wieder als Kommentar in den Code geschrieben.


```
public double macheNxNEineDimensionKleinerX(int n, double [][] matrix) // Macht eine NxN-Matrix zu N (N-1)x(N-1) Matritzen.
	{
		double ergebnis = 0;
		double multiplikator = 2;
		double determinante = 0;
		double zwischenResult = 0;
		double[][] matrixHelp = new double[n-1][n-1];
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
				{
					matrixHelp[(j+(n-2))%(n-1)][((k+(n-2))%(n-1))] = matrix[(j+i)%n][k];
				}
			}
			if (n == 3)
			{
				zwischenResult = calculateDeterminante3x3(n, matrix);
//				System.out.println(zwischenResult);
//				System.out.println(matrix[i][0]);
//				computeResult (zwischenResult, 1.0);
			}
			else if (n > 3)
			{
				zwischenResult = macheNxNEineDimensionKleinerX((n-1), matrixHelp);
				zwischenResult = zwischenResult * matrix[i][0];
				if ((i%2)!=0)
				{
					finale = finale - zwischenResult;
				}	
				else if(i%2==0)
				{
					finale = finale + zwischenResult;
				}
			}
			
//			System.out.println(zwischenResult * matrix[i][0]);
		}
		
//		for (int w = 0; w < n; w++)
//		{
//			System.out.println(matrix[w][0]);
//		}
		System.out.println(finale);				// HIER GIBT ES MIR JETZT 5 WERTE AUS. DER LETZTE DAVON IST BEI EINER 4X4-MATRIX DAS RICHTIGE ENDERGEBNIS. BEI 5X5 KLAPPT ES ALLERDINGS SCHON WIEDER NICHT MEHR!! :(
		return zwischenResult;
	}
```


----------



## SlaterB (5. Apr 2012)

welche Ausgaben zu welchem Aufruf gehören ist nicht ganz leicht festzustellen wenn sie ineinander geschachtelt sind, 
da muss man evtl. das Logging aufbohren, mit Leerzeichen einrücken oder sonstigen Prefixen verschiedene Ebenen markieren, 
zu Beginn der Methode einen definieren, in allen System.out.println() einfügen

abgesehen davon gilt genau das vorherige, kenne die Papierrechnung, vergleiche die Ergebnisse, neues kann ich nicht sagen,

wenn du aus irgendeinem Grund mit dem Vergleich nicht weiterkommst,
könntest du zumindest mir das Leben leichter machen, indem du dein 5x5-Matrix-Beispiel soweit verständlich hinschreibst,
wie es dir möglich und hier praktikabel ist, welche 4x4 Untermatrixen kommen raus, welche Unterdeterminanten sind dafür die richtigen Ergebnisse, was davon konntest du schon im Programm bestätigen,

wie sieht die letzte Formelzeile aus
5x5-det = 45 -24 + 66 - 34 + 9 = ? 
oder was genau?


----------



## Fant (5. Apr 2012)

Mal was zum grundsätzlichen Aufbau..

Du solltest dir eine Methode 
	
	
	
	





```
private double[][] unterMatrix(double[][] Matrix, int zeile, int spalte)
```
schreiben, die nichts weiter macht, als die entsprechende Untermatrix beim Streichen der Spalte _spalte_ und der Zeile _zeile_ zurückzugeben. Dann wird dein ganzer Code schon sehr viel übersichtlicher. Die Rekursive Berechnung der Determinante lässt sich dann in ~5? Zeilen aufschreiben.

Außerdem solltest du dir überlegen, was denn passiert, wenn eine 2x2 oder eine 1x1-Matrix eingegeben wird. Lass deine Rekursion doch einfach bis n=1 laufen. Die Determinante ist dann einfach der einzige Eintrag dieser Matrix.

Wenn du unbedingt (aus Performance-Gründen?) die 3x3-Matrix direkt berechnen willst, dann ist es hier m.M. nach wesentlich schöner und vermutlich auch schneller, wenn du direkt mit der Regel von Sarrus arbeitest.


```
private double det3x3Matrix(double[][] matrix) {
    return matrix[0][0]*matrix[1][1]*matrix[2][2]
          + matrix[0][1]*matrix[1][2]*matrix[2][0]
          + matrix[0][2]*matrix[1][0]*matrix[2][1]
          - matrix[0][2]*matrix[1][1]*matrix[2][0]
          - matrix[0][1]*matrix[1][0]*matrix[2][2]
          - matrix[0][0]*matrix[1][2]*matrix[2][1];
}
```

Ich hoffe ich hab jetzt nicht die Indizes durcheinandergewürfelt  Hier weiß jedoch jeder, der den Code sieht, sofort, was denn eigentlich berechnet werden soll.


----------



## AsterixdGallier (5. Apr 2012)

SlaterB hat gesagt.:


> welche Ausgaben zu welchem Aufruf gehören ist nicht ganz leicht festzustellen wenn sie ineinander geschachtelt sind,
> da muss man evtl. das Logging aufbohren, mit Leerzeichen einrücken oder sonstigen Prefixen verschiedene Ebenen markieren,
> zu Beginn der Methode einen definieren, in allen System.out.println() einfügen
> 
> ...



Naja die 5X5-Matritzen:

```
matrix [0][0] = 1;
		matrix [0][1] = -2;
		matrix [0][2] = 2;
		matrix [0][3] = 3;
		matrix [0][4] = 3;

		matrix [1][0] = 4;
		matrix [1][1] = 3;
		matrix [1][2] = 1;
		matrix [1][3] = -1;
		matrix [1][4] = 0;
		
		matrix [2][0] = 5;
		matrix [2][1] = -1;
		matrix [2][2] = 1;
		matrix [2][3] = 2;
		matrix [2][4] = 7;
		
		matrix [3][0] = -1;
		matrix [3][1] = 0;
		matrix [3][2] = 0;
		matrix [3][3] = 1;
		matrix [3][4] = 6;
		
		matrix [4][0] = 1;
		matrix [4][1] = 10;
		matrix [4][2] = 3;
		matrix [4][3] = 4;
		matrix [4][4] = 3;

Dann berechnet er halt die dazugehörigen 4x4 Matritzen, das sind dann 4 Stück:



1:
[3.0, 1.0, -1.0, 0.0], [-1.0, 1.0, 2.0, 7.0], [0.0, 0.0, 1.0, 6.0], [10.0, 3.0, 4.0, 3.0]

Die hat jetzt 4 3x3-Matritzen:
1:
[1.0, 2.0, 7.0], [0.0, 1.0, 6.0], [3.0, 4.0, 3.0]

2:
[0.0, 1.0, 6.0], [3.0, 4.0, 3.0], [1.0, -1.0, 0.0]

3:
[3.0, 4.0, 3.0], [1.0, -1.0, 0.0], [1.0, 2.0, 7.0]

4:
[1.0, -1.0, 0.0], [1.0, 2.0, 7.0], [0.0, 1.0, 6.0]




2:
[-1.0, 1.0, 2.0, 7.0], [0.0, 0.0, 1.0, 6.0], [10.0, 3.0, 4.0, 3.0], [-2.0, 2.0, 3.0, 3.0]

Wieder 4 3x3:

1:
[0.0, 1.0, 6.0], [3.0, 4.0, 3.0], [2.0, 3.0, 3.0]

2:
[3.0, 4.0, 3.0], [2.0, 3.0, 3.0], [1.0, 2.0, 7.0]

3:
[2.0, 3.0, 3.0], [1.0, 2.0, 7.0], [0.0, 1.0, 6.0]

4:
[1.0, 2.0, 7.0], [0.0, 1.0, 6.0], [3.0, 4.0, 3.0]




3:
[0.0, 0.0, 1.0, 6.0], [10.0, 3.0, 4.0, 3.0], [-2.0, 2.0, 3.0, 3.0], [3.0, 1.0, -1.0, 0.0]

Wieder 4 3x3:

1:
[3.0, 4.0, 3.0], [2.0, 3.0, 3.0], [1.0, -1.0, 0.0]

2:
[2.0, 3.0, 3.0], [1.0, -1.0, 0.0], [0.0, 1.0, 6.0]

3:
[1.0, -1.0, 0.0], [0.0, 1.0, 6.0], [3.0, 4.0, 3.0]

4:
[0.0, 1.0, 6.0], [3.0, 4.0, 3.0], [2.0, 3.0, 3.0]




4:
[10.0, 3.0, 4.0, 3.0], [-2.0, 2.0, 3.0, 3.0], [3.0, 1.0, -1.0, 0.0], [-1.0, 1.0, 2.0, 7.0]

Wieder 4 3X3:

1:
[2.0, 3.0, 3.0], [1.0, -1.0, 0.0], [1.0, 2.0, 7.0]

2:
[1.0, -1.0, 0.0], [1.0, 2.0, 7.0], [3.0, 4.0, 3.0]

3:
[1.0, 2.0, 7.0], [3.0, 4.0, 3.0], [2.0, 3.0, 3.0]

4:
[3.0, 4.0, 3.0], [2.0, 3.0, 3.0], [1.0, -1.0, 0.0]
```


Die sehen meiner Meinung nach doch richtig aus oder?


----------



## SlaterB (5. Apr 2012)

was sind die Ergebnisse, die Unterdeterminaten dazu?
was das Programm dann meint kann ich schon nachschauen, 
aber aus welchen Grund glaubst du bzw. weißt du hoffentlich recht sicher, dass das Programm falsch rechnet,
welche Zahl weicht ab?

die Matrixen sind gut zu wissen, noch wichtiger wären aber die simplen Einzelzahlen, die Determinanten


----------



## Fant (5. Apr 2012)

AsterixdGallier hat gesagt.:


> Naja die 5X5-Matritzen:
> 
> Dann berechnet er halt die dazugehörigen 4x4 Matritzen, das sind dann 4 Stück:



Wenn du den Laplaceschen Entwicklungssatz zur Berechnung einer 5x5-Matrix verwendest, kommst du im nächst Schritt zu FÜNF 4x4-Matrizen!


----------



## AsterixdGallier (5. Apr 2012)

Fant hat gesagt.:


> Mal was zum grundsätzlichen Aufbau..
> 
> Du solltest dir eine Methode
> 
> ...



Meinst du sowas?

```
public double[][] unterMatrix(double[][] matrix, int zeile, int spalte)
	{
		{
		double[][] matrixHelp = new double[zeile][spalte];
		for (int i = 0; i < spalte; i++)
		{
			for (int j = 0; j < zeile; j++)
			{
				for (int k = 0; k < zeile; k++)
				{
					matrixHelp[(j+(spalte-1))%(zeile)][((k+(spalte-1))%(spalte))] = matrix[(j+i)%zeile][k];
				}
//				System.out.println(matrixHelp[4][3]);
			}
			
//			System.out.println(matrixHelp[4][0]);
		}
		return matrixHelp;
	}
```
In wie weit hilft mir das jetzt weiter. Jetzt kriege ich immer EINE unter Matrix zu einer anderen, aber eben immer nur eine. Brauche ja alle


----------



## SlaterB (5. Apr 2012)

wie kann der Hinweis zu einer anderen 3x3-Berechnung oder Einführung einer Untermethode (hatte ich auch mal versucht zu erwähnen) die Anzahl der Unter-Matrixen ändern?
nicht immer so viel hineininterpretieren

der Hinweis von Fant scheint wichtig, bis ich genauer reinschauen könnte würde es noch etwas dauern


----------



## AsterixdGallier (5. Apr 2012)

SlaterB hat gesagt.:


> was sind die Ergebnisse, die Unterdeterminaten dazu?
> was das Programm dann meint kann ich schon nachschauen,
> aber aus welchen Grund glaubst du bzw. weißt du hoffentlich recht sicher, dass das Programm falsch rechnet,
> welche Zahl weicht ab?
> ...


Die unterdeterminanten habe ich bei 5x5 noch nicht gecheckt, weil sie bei 4x4 geklappt haben und ich keinen grund wüsste warum sie bei 5x5 nicht hinhauen soltlen. habe einfach auf: Berechnung von Determinanten meine matrix eingegeben und das ergebnis von den berechnungen verglichen leider weicht es ab..


----------



## SlaterB (5. Apr 2012)

> weil sie bei 4x4 geklappt haben und ich keinen grund wüsste warum sie bei 5x5 nicht hinhauen soltlen

sowas ist immer gefährlich, 4x4 ist gerademal eine Stufe über 3x3, welches schon Sonderbehandlung hat,
eine echte Rekursion sollte schon ein paar Ebenen hindurch getestet werden, 5x5 komplett geprüft wäre ein gutes Beispiel
(also testen wolltest du es ja natürlich, das ist das wichtigste, aber wäre auch gut die Zwischenschritte selber zu kennen)

wie steht es darum dass 5 Untermatrixen nötig sind? aber sollte in dem Programm ja auch so funktionieren,
na ich kann vorerst nicht mehr als solche schlauen Sätze sagen, nicht wirklich helfen, später dann vielleicht genauer reinschauen


----------



## Fant (5. Apr 2012)

AsterixdGallier hat gesagt.:


> danke meine untermatritzen sind richtig



Bist du dir sicher? Du hast da komische Zeilenpermutationen drin. Das ist in jedem Fall fehleranfällig und hat eventuell einen Vorzeichenfehler in deinen Berechnungen zur Folge.


Bei meinem Hinweis mit der Methode zu Berechnung der Untermatrix meinte ich, dass jeweils die Spalte mit dem Index _spalte_ und die Zeile mit dem Index _zeile_ gelöscht werden soll.

Für A = [(1,2,3),(4,5,6),(7,8,9)] soll dann etwa der Aufruf _unterMatrix(A,0,0)_ das Array [(5,6),(8,9)] zurückliefern. Der Aufruf _unterMatrix(A,1,2)_ liefert [(1,2),(7,8)] usw..


Und jetzt nimm dir einfach mal ein Blatt Papier, schreib eine beliebige 5x5-Matrix auf und überlege dir, wie (nur) der erste Schritt bei der Berechnung der Determinante (nach Laplace) aussieht. Dann schreibt sich die Rekursion nahezu von selbst...


----------



## AsterixdGallier (5. Apr 2012)

Fant hat gesagt.:


> Bist du dir sicher? Du hast da komische Zeilenpermutationen drin. Das ist in jedem Fall fehleranfällig und hat eventuell einen Vorzeichenfehler in deinen Berechnungen zur Folge.
> 
> 
> Bei meinem Hinweis mit der Methode zu Berechnung der Untermatrix meinte ich, dass jeweils die Spalte mit dem Index _spalte_ und die Zeile mit dem Index _zeile_ gelöscht werden soll.
> ...



hi habe jetzt einen code gemacht wo ich die gewünschte spalte auslassen kann, zeile wird meiner meinung nach für nxn nicht benötigt oder?


```
public double[][] unterMatrix(double[][] matrix,int n, int spalte, int zeile)
	{
	double[][] matrixHelp = new double[n-1][n-1];
		for (int i = 0; i < n-1; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
				{
					matrixHelp[(j+(n-spalte))%(n-1)][((k+(n-2))%(n-1))] = matrix[(j+i+(spalte+2))%n][k];
				}
			}
		}
	return matrixHelp;
	}
```


----------



## SlaterB (5. Apr 2012)

ich schau jetzt etwas nach, zwei sofort auffällige Punkte:
du gibst finale aus, aber finale nicht zurück, sondern zwischenergebnis, 
da kann sich der Aufrufer (z.B. die höhere Ebene für 5x5) ja über einen falschen Wert freuen..

für n== 3 rechnest du in der Schleife x-mal dasselbe aus, 
es reicht doch das EINMAL vor der Schleife zu machen und fertig

und noch ein dritter Punkt: ein Instanzattribut finale ist ja vollkommen verrückt,
damit addierst du ja die Zwischenwerte über mehrere Ebenen zusammen?!

jeder Methodendurchlauf von macheNxNEineDimensionKleinerX() sollte für sich in lokalen Variablen ohne Einflüsse von außen,
fertige korrekte Ergebnisse gewünschter rekursiver Aufrufe abgesehen, arbeiten.., 
das ist ja noch ein sehr bedenklicher Fehler, wie kann man sowas einbauen? eine Variable die von verschiedensten Schleifen im gesamten Programm bearbeitet wird

hier vorerst neuer Code,
da du noch nichtmal das erhoffte Endergebnis gepostet hast, weiß ich nicht ob richtig, 1486 kommt raus,
für die Webseite muss ich die 5x5-Matrix auch erst noch mühevoll die Zahlen extrahieren,
den Punkt hast du dir gespart


```
public double macheNxNEineDimensionKleinerX(int n, double[][] matrix)
    {
        if (n == 3)
        {
            return calculateDeterminante3x3(n, matrix);
        }

        double ergebnis = 0;
        double multiplikator = 2;
        double determinante = 0;
        double[][] matrixHelp = new double[n - 1][n - 1];
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                for (int k = 0; k < n; k++)
                {
                    matrixHelp[(j + (n - 2)) % (n - 1)][((k + (n - 2)) % (n - 1))] = matrix[(j + i) % n][k];
                }
            }

            double zwischenResult = macheNxNEineDimensionKleinerX(n - 1, matrixHelp);
            zwischenResult = zwischenResult * matrix[i][0];
            if ((i % 2) != 0)
            {
                ergebnis = ergebnis - zwischenResult;
            }
            else
            {
                ergebnis = ergebnis + zwischenResult;
            }

        }
        System.out.println("n: " + n + " -> " + ergebnis);
        return ergebnis;
    }
```


----------



## AsterixdGallier (5. Apr 2012)

So ich habe jetzt neuen hoffentlich übersichtlicheren code gemacht.


```
else if (n > 3)
		{
			double finale2 = 0;
			double zr = 0;
			for (int r = 0; r < n; r++)
			{
				double[][] a = unterMatrix(matrix, n,r,0);
				zr = matrix[r][0]*calculateDeterminante3x3(n-1, a);
				if ((r%2)!=0)
					{
					finale2 = finale2 - zr;
					}	
				else
				{
					finale2 = finale2 + zr;
				}
				
			}
			System.out.println(finale2);
		}
```


```
public double[][] unterMatrix(double[][] matrix,int n, int spalte, int zeile)
	{
	double[][] matrixHelp = new double[n-1][n-1];
		for (int i = 0; i < n-1; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
				{
					matrixHelp[(j+(n-spalte))%(n-1)][((k+(n-2))%(n-1))] = matrix[(j+i+(spalte+2))%n][k];
				}
			}
		}
	return matrixHelp;
	}
```
4x4 klappt mal wieder.
5x5 kommt -2840 raus, sollte aber laut internet 1610.
habe jetzt diese methode die die gewünschte spalte rauslässt und das passiert halt mit jeder einmal und wird dann mit multipliziert.


----------



## Fant (5. Apr 2012)

Die Zeilenpermutationen sind immer noch drin. Hast du das bei deinen Berechnungen berücksichtigt?

Auch versteh ich nicht so wirklich, was deine Methode da macht. Du durchläufst da defintiv eine Schleife mehr durch, als nötig wär. Bei großen Matrizen wird das tödlich ... bei n=10 hast du so schon tausend Schleifendurchläufe statt hundert, bei n=1000 sind es 1 Mrd. statt einer Million ... da wird einem schnell schwindelig *g*

Wenn du bei einer nxn Matrix nur eine Spalte streichst, dann bekommst du eine nx(n-1) Matrix. Du willst aber doch wieder eine quadratische Matrix haben. Wenn du aber immer nach der ersten Zeile entwickeln willst, dann musst du das natürlich nicht extra als Argument übergeben. Allerdings ist der Mehraufwand bei der Implementierung so verschwindend gering, dass du dich fragen solltest, ob du aus so ein nützliches Extra wirklich verzichten willst? 

Mein Vorschläg wäre da einfach so etwas:


```
public static double[][] unterMatrix(double [][] matrix, int zeile, int spalte) {
        double [][] unterMatrix = new double[matrix.length-1][matrix.length-1];
        int zeilenOffset=0, spaltenOffset=0;

        for(int z=0; z<unterMatrix.length; z++){
            spaltenOffset=0;
            if(zeile==z) zeilenOffset=1;
            for(int sp=0; sp<unterMatrix.length; sp++){
                if(spalte==sp) spaltenOffset=1;
                unterMatrix[z][sp]= matrix[z+zeilenOffset][sp+spaltenOffset];
            }
        }
        return unterMatrix;
}
```

Ganz naiv angegangen. Da hast du auch nicht diese störenden Permutationen drin.


----------



## Fant (5. Apr 2012)

Zu deinem Code-Schnipsel:

Du weißt doch gar nicht, ob _a_ eine 3x3-Matrix ist, rufst aber trotzdem die Methode zur Berechnung der Determinante einer 3x3-Matrix auf. Das kann doch gar nicht funktionieren, wenn du die det einer 5x5-Matrix berechnen willst und in a dann jeweils eine 4x4-Matrix steckt!


----------



## SlaterB (5. Apr 2012)

da haben wir ja alle einen schönen verwurschtelten Thread zustande gebracht, nun kann man mit Einzeltipps kaum mehr was erreichen,

ich habe hier jetzt eine Version, die 1610 berechnet,
ich erinnere an mein vorheriges Posting, vielleicht übersehen, besonders die finale-Variable war falsch,
und darüber hinaus war dann noch ein Fehler falsche Untermatrixen, Zeilen-Ordnung seltsam

für 4x4 aus spielte die Reihenfolge der Zeilen in 3x3-Matrixen keine so große Rolle, es kam auch mit Vertauschung dasselbe raus,
bei 5x5 sind richtige 4x4er aber schon wichtig, mit der neuen Untermethode kommen richtige raus, insgesamt 1610


```
class Mathetool
{
    int zähl = 0;
    double result = 0;
    double multiplikator = 1;

    public static void main(String[] args)
    {
        int n = 5;

         double[][] matrix = new double[n][n];
         matrix[0][0] = 1;
         matrix[0][1] = -2;
         matrix[0][2] = 2;
         matrix[0][3] = 3;
         matrix[0][4] = 3;
         // matrix [0][5] = 11;
        
         matrix[1][0] = 4;
         matrix[1][1] = 3;
         matrix[1][2] = 1;
         matrix[1][3] = -1;
         matrix[1][4] = 0;
         // matrix [1][5] = 6;
        
         matrix[2][0] = 5;
         matrix[2][1] = -1;
         matrix[2][2] = 1;
         matrix[2][3] = 2;
         matrix[2][4] = 7;
         // matrix [2][5] = 1;
        
         matrix[3][0] = -1;
         matrix[3][1] = 0;
         matrix[3][2] = 0;
         matrix[3][3] = 1;
         matrix[3][4] = 6;
         // matrix [3][5] = 5;
        
         matrix[4][0] = 1;
         matrix[4][1] = 10;
         matrix[4][2] = 3;
         matrix[4][3] = 4;
         matrix[4][4] = 3;
        // matrix [4][5] = 10;

        // matrix [5][0] = 1;
        // matrix [5][1] = 12;
        // matrix [5][2] = 14;
        // matrix [5][3] = 1;
        // matrix [5][4] = 2;
        // matrix [5][5] = 6;

// so kann man auch kürzer definieren:
//        double[][] matrix =
//            {
//                {3, 1, -1, 0},
//                {-1, 1, 2, 7},
//                {0, 0, 1, 6},
//                {10, 3, 4, 3}};


        Mathetool matheTool = new Mathetool();
        matheTool.determinanteAll(n, matrix);
    }

    public double determinanteAll(int n, double[][] matrix)
    {
        if (n == 3)
        {
            return calculateDeterminante3x3(n, matrix);
        }
        if (n > 3)
        {
            return macheNxNEineDimensionKleinerX(n, matrix);
        }
        throw new RuntimeException();
    }

    public double calculateDeterminante3x3(int n, double[][] matrix)
    {
        double determinante = 0;
        double zwischenErgebnisAddition = 0;
        double zwischenErgebnisSubtrahtion = 0;
        double matrixElement = 1;
        double matrixElement2 = -1;
        int j = 2;
        int k = 0;
        for (int p = 0; p < n; p++)
        {
            matrixElement = 1;
            matrixElement2 = -1;
            for (int i = 0; i < n; i++)
            {
                matrixElement = matrix[k][i] * matrixElement;
                // System.out.println( matrix[k][i]);
                matrixElement2 = matrix[k][j] * matrixElement2;
                j = j - 1;
                if (j == -1)
                {
                    j = n - 1;
                }
                k = (k + 1) % n;
            }
            zwischenErgebnisAddition = zwischenErgebnisAddition + matrixElement;
            // System.out.println(zwischenErgebnisAddition);
            zwischenErgebnisSubtrahtion = zwischenErgebnisSubtrahtion + matrixElement2;
            determinante = zwischenErgebnisAddition + zwischenErgebnisSubtrahtion;
            k = k + 1;
        }
        // System.out.println("Determinante: " + determinante);
        return determinante;
    }


    public double macheNxNEineDimensionKleinerX(int n, double[][] matrix)
    {
        int kk = 3;
        if (n == 3)
        {
            return calculateDeterminante3x3(n, matrix);
        }

        double ergebnis = 0;
        double multiplikator = 2;
        double determinante = 0;
        double[][] matrixHelp = new double[n - 1][n - 1];
        for (int i = 0; i < n; i++)
        {
            matrixHelp = unterMatrix(matrix, i, 0);
            // for (int j = 0; j < n; j++)
            // {
            // for (int k = 0; k < n; k++)
            // {
            // matrixHelp[(j + (n - 2)) % (n - 1)][((k + (n - 2)) % (n - 1))] = matrix[(j
            // + i) % n][k];
            // }
            // }
            double zwischenResult = macheNxNEineDimensionKleinerX(n - 1, matrixHelp);
            double fac = matrix[i][0];
            zwischenResult = zwischenResult * fac;

            if ((i % 2) != 0)
            {
                ergebnis = ergebnis - zwischenResult;
            }
            else
            {
                ergebnis = ergebnis + zwischenResult;
            }

        }
        System.out.println("n: " + n + " -> " + ergebnis);
        return ergebnis;
    }

    public static double[][] unterMatrix(double[][] matrix, int zeile, int spalte)
    {
        double[][] unterMatrix = new double[matrix.length - 1][matrix.length - 1];
        int zeilenOffset = 0, spaltenOffset = 0;

        for (int z = 0; z < unterMatrix.length; z++)
        {
            spaltenOffset = 0;
            if (zeile == z) zeilenOffset = 1;
            for (int sp = 0; sp < unterMatrix.length; sp++)
            {
                if (spalte == sp) spaltenOffset = 1;
                unterMatrix[z][sp] = matrix[z + zeilenOffset][sp + spaltenOffset];
            }
        }
        return unterMatrix;
    }
}
```


----------



## Fant (5. Apr 2012)

Und nur mal zum Vergleich, wie kurz und übersichtlich der Code wird, wenn du auf das gesonderte Berechnen der Determinanten von 3x3-Matrizen und sonstigen Schnick-Schnack verzichtest


```
public static double[][] unterMatrix(double [][] matrix, int zeile, int spalte) {
    double [][] unterMatrix = new double[matrix.length-1][matrix.length-1];
    int zeilenOffset=0, spaltenOffset=0;

    for(int z=0; z<unterMatrix.length; z++){
        spaltenOffset=0;
        if(zeile==z) zeilenOffset=1;
        for(int sp=0; sp<unterMatrix.length; sp++){
            if(spalte==sp) spaltenOffset=1;
            unterMatrix[z][sp]= matrix[z+zeilenOffset][sp+spaltenOffset];
        }
    }
    return unterMatrix;
}

public static double determinant(double[][] matrix) {
    if(matrix.length==1) return matrix[0][0];
    else {
        double determinant = 0;
        for(int i=0; i<matrix.length; i++) {
            determinant += (i%2==0?1:-1)*matrix[i][0]*determinant(unterMatrix(matrix,i,0));
        }
        return determinant;
    }
}
```

...und dann funktioniert er sogar auch für 2x2- und 1x1-Matrizen


----------



## AsterixdGallier (5. Apr 2012)

Fant hat gesagt.:


> Zu deinem Code-Schnipsel:
> 
> Du weißt doch gar nicht, ob _a_ eine 3x3-Matrix ist, rufst aber trotzdem die Methode zur Berechnung der Determinante einer 3x3-Matrix auf. Das kann doch gar nicht funktionieren, wenn du die det einer 5x5-Matrix berechnen willst und in a dann jeweils eine 4x4-Matrix steckt!



habe ich auch gerade gemerkt das war ziemlich dämlich von mir..


----------



## AsterixdGallier (5. Apr 2012)

SlaterB hat gesagt.:


> da haben wir ja alle einen schönen verwurschtelten Thread zustande gebracht, nun kann man mit Einzeltipps kaum mehr was erreichen,
> 
> ich habe hier jetzt eine Version, die 1610 berechnet,
> ich erinnere an mein vorheriges Posting, vielleicht übersehen, besonders die finale-Variable war falsch,
> ...



tatsache vielen dank den werd ich mir jetzt erstmal genau ansehen.


----------



## SlaterB (5. Apr 2012)

Fant hat gesagt.:


> Und nur mal zum Vergleich, wie kurz und übersichtlich der Code wird, wenn du auf das gesonderte Berechnen der Determinanten von 3x3-Matrizen und sonstigen Schnick-Schnack verzichtest


die separate Methode kann man haben oder nicht haben, hat auf die Hauptmethoden wenig Einfluss,
je nach Umsetzung und Code-Stil nur eine Zeile Aufruf

den Rest hast du auch deutlich verkürzt, aber das hat ja nix mit 3x3 zu tun sondern allein dieselbe Methode viel kürzer ohne Variablen-Deklarationen, if/else Unterschied usw.


----------



## AsterixdGallier (5. Apr 2012)

AsterixdGallier hat gesagt.:


> tatsache vielen dank den werd ich mir jetzt erstmal genau ansehen.



durch diese ganzen rekursionen wird sobald n = 5 oder höher ist es richtig schwer nachzuvollziehen.
was genau ist jetzt in der ausgabe sobald n > 4?
für n = 4 bin ich im kopf es einmal durchgegangen und habs halbwegs verstanden.


----------



## SlaterB (5. Apr 2012)

wen fragst du was genau? am Ende ist nur der Rückgabewert wichtig?


----------



## AsterixdGallier (5. Apr 2012)

SlaterB hat gesagt.:


> wen fragst du was genau? am Ende ist nur der Rückgabewert wichtig?



simmt schon wollte halt nachvollziehen welche werte davor ausgegeben werden.


----------



## SlaterB (5. Apr 2012)

na wenn das nicht direkt sichtbar ist..,
die Ausgabe gibt jede errechnete Determinante bis auf die 3er,
also zuerst die 5 4er in Reihenfolge, dann die 5er


----------



## AsterixdGallier (5. Apr 2012)

SlaterB hat gesagt.:


> na wenn das nicht direkt sichtbar ist..,
> die Ausgabe gibt jede errechnete Determinante bis auf die 3er,
> also zuerst die 5 4er in Reihenfolge, dann die 5er



oh ja klar logisch hatte das ganze mit n = 6 laufen, da wirds unübersichtlicher..
aber habs jetz begriffen danke


----------

