# zweidim. Array - Matrix auf ob. Dreiecksmatrix prüfen



## Jo.Mo. (10. Dez 2010)

Problem steht eigentlich schon im Topic. Ich soll eine quadratische Matrix, ergo ein 2-dimensionales Array prüfen, ob es im linken unteren Bereich Nullen enthält. Was dann ja einer oberen Dreiecksmatrix entsprechen sollte...  Das ganze soll als Methode implementiert werden.

Ich hatte verschd. Möglichkeiten mittels for-Schleife versucht, das hat aber nix getaugt. Da ich ja im Endeffekt nur auf boolean prüfe, vermute ich, ich stell mich zu doof an oder es hat jemand eine idee, wie man das kurz und schmerzlos lösen kann.

mein letzter Ansatz sah etwa so aus:

```
public class MatrixOperation {

    public static boolean pruefe (int[][] matrix)

    	for (int i = n-1; i > -1 n; i--) {

            sum = 0;

            for (j = i + 1; j < n; j++) {

                sum += u[i][j]*x[j];

            }

            x[i] = (y[i] - sum)/u[i][i];
          
          return true;  
    	}



    public MatrixOperation() {
    }


}
```


----------



## Final_Striker (10. Dez 2010)

Jo.Mo. hat gesagt.:


> ```
> 
> ```



recht dünn der Ansatz, meinst du nicht? ;-)


----------



## Jo.Mo. (11. Dez 2010)

...sorry, da ist wohl was schiefgegangen, wird gleich geändert... 

...ich weiss nicht, ob es mit einer anderen Bedingungsart nicht vielleicht eleganter wäre. Mir gehts aber in erster Linie darum, was funktionsfähiges gebacken zu bekommen. Mit den throw-Sachen komme ich noch nicht ganz klar, aber irgendeine Möglichkeit, Fehler abzufangen (und in dem Falle false zurückzugeben) will ich schon noch einbauen...


----------



## Jo.Mo. (11. Dez 2010)

EDIT: Achso, Nebenfrage: Was muss denn zwingend in der Main-Methode stehen, damit ich die korrekte Funktionsweise der Methode prüfen kann...?


----------



## XHelp (11. Dez 2010)

Die äußere Schleife macht kein Sinn, weil du direkt im 1. Schritt etwas zurückgibst. Summe brauchst du auch nicht. Du musst ja nur Prüfen, ob sich eine Zahl die !=0 ist sich in bestimmten Bereichen befindet:

```
1 2 3 4 //0. Zeile
0 5 6 7 //du bist in der 1. Zeile und 1 Zahl von links soll 0 sein
0 0 9 1 //du bist in der 2. Zeile und 2 Zahlen von links sollen 0 sein
0 0 0 2 //du bist in der 3. Zeile und 3 Zahlen von links sollen 0 sein
// du bist in der n. Zeile und n Zahlen von links sollen 0 sein
```
Das Muster müsste erkennbar sein.

Außerdem greifst du in deiner Methode auf irgendwelche völlig anderen Matritzen zu.


----------



## Final_Striker (11. Dez 2010)

ich würde so was machen wie


```
public static boolean pruefe (int[][] matrix)
{
   for (int i =...) {

      for (int j = ...) {

         if(matrix[i][j] != 0)
            return false;
      }
   }
   return true;  
}
```

jetzt musst du nur noch die Schleifen über das Drittel der Matrix laufen lassen. ;-)


----------



## Jo.Mo. (11. Dez 2010)

...tja, wenn ich jetzt wüsste wie ich das auf die Dreiecksform begrenze, wär ich glücklich. Ausgehend davon, das i die zeilen sind und j die Spalten, fange ich doch erst in der zweiten Zeile an, und addiere dann als vorgabe für die Anzahl der Nullen pro Zeile um eins auf. Ich weiss nicht ob es so hinhaut, also immer her mit der kritik. 


```
public class MatrixOperation {

    	public static boolean pruefe (int[][] matrix) {
    		
            for (int i = 1; i < n; i++) {
 
                for (int j = 2; j < n; j++) {
 
                    if(matrix[i][j] != 0)
                      return false;
                }
            }
            return true;  
        }



    public MatrixOperation() {
    }


}
```


----------



## XHelp (11. Dez 2010)

Das j sollte bei 0 anfangen.

```
j<n
```
 stimmt auch nicht. Du musst ja es irgendwie abhängig von der Zeilennummer (und nicht -anzahl) machen. Also würde es sich anbieten sowas wie 
	
	
	
	





```
j<i
```
 zu machen.


----------



## Jo.Mo. (11. Dez 2010)

...vielleicht habe ich einen denkfehler, aber wie komme ich dadurch auf die Dreiecksform...? Ich glaub ich muss mir über die Feiertage nochmal einiges an Lektüre vornehmen...


----------



## XHelp (11. Dez 2010)

in der 1. Zeile überprüfst du 1 Zahl, in der 2. - 2, in der 3. - 3. Hört sich nach einem Dreieck an.


----------



## Jo.Mo. (12. Dez 2010)

genau das habe ich ja schon im letzten Post geschrieben. Vielleicht liegts daran das ich mit dem j und i nicht klarkomme. i sind die Zeilen, j die Spalten, oder? Und aus der Bedingung Zeilen grösser Spalten ist für mich noch kein Dreieck ersichtlich. Vielleicht seh ich den Wald vor lauter Bäumen nicht, und ich habe da auch keine Sicht wie ein Java-Pro, ich schau es mir morgen vormittag nochmal an.


----------



## Final_Striker (12. Dez 2010)

1 2 3 4
0 5 6 7 
0 0 9 1 
0 0 0 2 

Die erste for-Schleife läuft über die Zeilen und dir zweite for-Schleife über die Spalten. Du musst zwar über alle Zeilen laufen (ok, über die erste ist es unnötig, aber was solls) aber nicht über alle Spalten. Das bedeutet, du musst die Bedingung wie lange die zweite Schleifen laufen muss anpassen.

Wenn du dir die Matrix anschaust und überprüfst wie lange die zweite Schleife immer in einer Zeile laufen muss, sollte dir eine Abhängigkeit zwischen den Zeilennummer und der Anzahl der Nullen auffallen.


----------



## Jo.Mo. (12. Dez 2010)

Final_Striker hat gesagt.:


> ...und überprüfst wie lange die zweite Schleife immer in einer Zeile laufen muss, sollte dir eine Abhängigkeit zwischen den Zeilennummer und der Anzahl der Nullen auffallen



...du meinst, wie lange die Zweite Zeile in einer Spalte laufen muss, oder? Die erste Bedingung kann dann ja so bleiben, nur die zweite, also j, die Spalten, sollte, wenn ich dich richtig verstanden habe, in diese Richtung gehen...


```
public class MatrixOperation {

    	public static boolean pruefe (int[][] matrix) {

            for (int i = 0; i < n; i++) {

                for (int j = i+1; j < i; j++) {

                    if(matrix[i][j] != 0)
                      return false;
                }
            }
            return true;
        }



    public MatrixOperation() {
    }


}
```

...wenn ich den Bedingungsablauf richtig interpretiere, sollte er doch jetzt, solange die Spaltenanzahl noch nicht die Zeilenanzahl ist, prüfen ob in dr 2. Zeile eine Null, in der 3. 2 Nullen usw. stehen. Oder anders ausgedrückt müssen in der 1. Spalte 3 Nullen, in der 2.Spalte 2 Nullen und in der 3. Spalte 1 Null stehen. Über den letzten Teil bin ich mir schon im klaren, nur über den for-Ablauf rätsel ich. 

Die 3 Anweisungen in der for-schleife sagen ja: Setze den Zähler auf ...; prüfe ob der Zahler kleiner/gleich ... ist; inkrementiere um 1.


----------



## XHelp (12. Dez 2010)

Warum das i+1? Dadurch betrachtest du den 0. Werte einer Zeile nicht.


----------



## Final_Striker (12. Dez 2010)

Deine Schleife läuft jetzt genau über die andere Dreieckshälfte. ;-)


----------



## XHelp (12. Dez 2010)

Naja, um genau zu sein läuft die Schleife jetzt überhaupt nicht. Weil der Wert am Anfang 
	
	
	
	





```
i+1
```
 ist und die Schleifenbedingung 
	
	
	
	





```
j<i
```
 ist


----------



## Final_Striker (12. Dez 2010)

Ach stimmt, sorry. Hab das [c]j < i[/c] übersehen.

Edit:

@Jo.Mo.

Mal ein Tipp, wenn du mal nicht weiterkommst, einfach ein Blatt Papier nehmen und die Sachen aufzeichnen.

Lass am besten auch die erste Zeile der Matrix weg, also i von 1 und nicht von 0 laufen lassen -> [c]int i = 1[/c]

Matrix n = 4

1 2 3 4
0 5 6 7
0 0 9 1
0 0 0 2 


```
Zeile (i).   j muss von - bis laufen

1.   0 - 0
2.   0 - 1
3.   0 - 2
```
Vergleiche jetzt die Zeilennummer mit der Position bis zu der j laufen muss.


----------



## Jo.Mo. (12. Dez 2010)

...also i-1? Was ich im letzten Post geschrieben hab, stimmt doch, oder? Könnt ihr mir zumindest einen Tip geben oder aufklären, ob ich das mit der Schleife richtig verstehe? Wenn ich weder sicher sein kann, ob ich den Bedingungsablauf richtig interpretiere noch einen Ansatz dahingehend habe, kann ich nur raten - wenig zielführend...


----------



## XHelp (12. Dez 2010)

Ich habe so das Gefühl, dass ich es schon mal geschrieben habe....


XHelp hat gesagt.:


> Das j sollte bei 0 anfangen.


----------



## Jo.Mo. (12. Dez 2010)

@Final Striker: Danke, werd ich gleich nochmal machen. Hatte das zwar anfangs so probiert, aber irgendwie bin ich mir unklar darüber, was durch die anweisungen genau passiert.

1. Die 3 Anweisungen in der for-schleife sagen ja: Setze den Zähler auf ...; prüfe ob der Zahler kleiner/gleich ... ist; inkrementiere um 1.

- stimmt doch, oder?

2.mit der 1. for-bedingung (i) durchlaufe ich die Zeilen, die 2. innere for schleife läuft spaltenweise durch (j), richtig?

EDIT: Irgendwie habe ich keinen Plan, was i und j eigentlich darstellen sollen - bzw. es sind Faktoren, die in der Bedingung festgelegt, geprüft und inkrementiert werden, aber mir fehlt da die Vorstellung wie ich durch die beiden verschachtelten bedingungen auf die Spalten und Zeilen einfluss nehme. Klingt doof, aber ich bin nicht sicher ob ich verstehe was durch die Bedingungen genau vorgeht, bzw. an welcher Stelle. ;(


----------



## Jo.Mo. (12. Dez 2010)

...ich arbeite mich jetzt mal vor. (ausgehend von dem Tip von Final Striker) 

Angenommen die Matrix ist n =4

1 2 3 4
0 5 6 7
0 0 9 1
0 0 0 2

for (i = 0; i < n; i++):
die erste Bedingung setzt den Zähler auf null, prüft, ob i (anfangs 0) kleiner als n (Dimension der Matrix) ist und inkrementiert dann um 1. - das läuft solange, wie i nicht 4 ist. Sind i nun die Spalten oder die Zeilen? Wenn Spalten, ist es richtig (weil in der letzten ja keine Nullen sind) wenn Zeilen geht er nur bis zur 3 Zeile (falsch, denn in der 4 zeile stehen ja 2 Nullen).

Solange die erste bedingung nicht erfüllt ist, springt er nach dem Inkremetieren auf die nächste Bedingung:

for (j = 0; j < i; j++): Setzt j auf 0, prüft, ob j kleiner i ist (was im ersten Anlauf dann 1 wäre), und inkrementiert ebenfalls um 1.

in der if Bedingung wird nun geprüft, ob die Matrix an der Stelle (hier im ersten Anlauf [1][0] den wert 0 hat - wenn nicht, wird false zurückgegeben und die 1. Bdeingung startet neu.

Habe ich das jetzt richtig nachvollzogen oder wo liegt mein Fehler...?


----------



## andiv (12. Dez 2010)

Das ist deine Matrix, i ist der Zeilenindex, j ist der Spaltenindex:

```
j=0 1 2 3 
i=
0  ? ? ? ?
1  0 ? ? ?
2  0 0 ? ?
3  0 0 0 ?
```

Überprüft werden müssen folgende Elemente:
matrix[1][0],
matrix[2][0], matrix[2][1]
matrix[3][0], matrix[3][1], matrix[3][2]

Wenn der Programmcode so aussieht

```
for (int i = 0; i < n; i++) {

    for (int j = 0; j < i; j++) {

        if(matrix[i][j] != 0)
            return false;
        }
}
return true;
```

dann laufen die Schleifen folgendermaßen
i=0: innere schleife wird nicht durchlaufen
i=1: j=0 da 0<1
i=2: j=0 da 0<2, j=1 da 1<2
i=3: j=0 da 0<3, j=1 da 1<3, j=2 da 2<3

Du solltest erkennen dass so genau die richtigen Elemente überprüft werden.


----------



## Final_Striker (12. Dez 2010)

[c]for(int j = 0; j < i; j++)[/c]

Laufe von 0, solange j kleiner i ist in einer Schritten [c]j++  <- identisch mit ->  j = j + 1[/c].


Und wie du oben schon geschrieben hast muss das [c]j[/c] immer bis [c]i-1[/c] laufen.


----------



## Jo.Mo. (12. Dez 2010)

...ah, jetzt wird mir einiges klar. Ich hatte schon nicht berücksichtigt das das array schon bei [0][0] anfängt, dachte an [1][1]. Dumm von mir.

Ich habe es zwar etwas schlecht und unübersichtlich formuliert, aber darauf wollte ich in etwa hinaus. Mein 2. Fehler war, das ich nicht berücksichtigt habe das die innere Schleife ab i=2 solange durchläuft bis j=i-1 ist. Also das erst [2][0] und anschliessend [2][1] geprüft wird, das hat mich da aus dem Konzept gebracht.


...was muss denn mindestens in der main-Methode stehen, damit ich den Ablauf testen kann?


```
public class MatrixOperation {

    	public static boolean pruefe (int[][] matrix) {

            for (int i = 0; i < n; i++) {

                for (int j = 0; j < i; j++) {

                    if(matrix[i][j] != 0)
                      return false;
                }
            }
            return true;
        }



    public MatrixOperation() {
    }


}
```

EDIT: @Final Striker: Ja, das inkrementieren war mir schon klar, nur um das j hatte ich einen Denkfehler, s.o.


----------



## Final_Striker (12. Dez 2010)

Die Matrix die du der Methode mitgeben musst.^^

außerdem

[c]for (int i = 0; i < n; i++) {[/c]

musst du anstatt n die Länge der Matrix einsetzen.


----------



## Jo.Mo. (12. Dez 2010)

```
public class MatrixOperation {

    	public static boolean pruefe (int[][] matrix) {
    		
    		if (){
    		   return null;

    		} else { for (int i = 0; i < n; i++) {

                   for (int j = 0; j < i; j++) {

                       if(matrix[i][j] != 0)
                         return false;
                   }
              } return true;
              }
    	}

        public static int[] matVek(int[][]m, int[]v) {

            int array2[][] = new int[3][3];
            for(int i = 0; i < x; i++) {
			    for(int j = 0; j < y-1; j++) {
				    for(int k = 0; k < y; k++){

					array2[i][j] += array[i][k]*array1[k][j];
				    }
			    }
            }
        }



    public static void main(String[] args) {


        int[][] array = new int[][];
    	int array[][] = {{5,6,7},{4,8,9}};
		int array1[][] = {{6,4},{5,7},{1,1}};

		System.out.print(" "+array2[i][j]);


    }


}
```


...irgendwelche Verbesserungsvorschläge? Ich habe zusätzlich noch eine  Multiplikationsoperation Matrix*Vektor eingebaut, noch nicht ganz fertig, und die pruefe Methode will ich grob absichern, dass er Referenz null zurückgibt, falls Multiplikation nicht möglich ist.

Die Arrays in der Main methode änder ich gerade, dass man diese selbst eingibt. Ergebnis poste ich gleich.


----------



## XHelp (12. Dez 2010)

Die If-Abfrage ist ziemlich sinnfrei. Außerdem kam ja schon der Tipp, dann du 
	
	
	
	





```
n
```
 wegmachen sollst und statt dessen 
	
	
	
	





```
matrix.length
```
 nehmen.
Die 2. Methode macht auch kein Sinn:
1. gibst du nichts zurück
2. greifst du wieder gar nicht auf die Werte zu, die man der Methode übergibt
3. wieder irgendwelche auf der Luft gegriffenen Zahlen.


----------



## Jo.Mo. (12. Dez 2010)

...warum ist die if-abfrage sinnfrei? Das noch nichts drinsteht ist mir bewusst, ich muss ja erstmal sehen was ich in der mainMethode übergebe um zu sehen auf was ich das prüfe. Es geht darum, dass bei unmöglichkeit einer Multiplikation "null" zurückgegeben werden soll. Was wäre denn für dich sinnvoll?

2. Ich hatte den anderen Teil schon mal vor einiger Zeit gemacht, jetzt bloss reinkopiert, klar, dass noch nicht alles passt. Sitz ich wie gesagt dran.

3. Das hatte ich auch geschrieben, dass ich die main Methode dahingehend ändere.

Kann es sein, dass ihr "Profis" eine Art Tunnelblick für Java-Codes entwickelt und den Rest in den Posts ignoriert...?


----------



## XHelp (12. Dez 2010)

Jo.Mo. hat gesagt.:


> Kann es sein, dass ihr "Profis" eine Art Tunnelblick für Java-Codes entwickelt und den Rest in den Posts ignoriert...?


Nö, in deinem Post hieß es ja:


Jo.Mo. hat gesagt.:


> ...irgendwelche Verbesserungsvorschläge?


Also wurde es ja doch nicht ignoriert.
Und wenn du weißt, dass die Methode syntaktisch falsch ist, wenn du weißt, dass die semantisch falsch ist, wenn du weißt, dass du die noch ändern wirst: warum postest du die überhaupt? oO

Deine Prüf-Methode prüft ob es eine Dreiecksmatrix ist und gibt entweder true oder false zurück. Da gibt es kien null... Und da kann es auch kein null geben, weil boolean nicht null sein kann.


----------



## Jo.Mo. (12. Dez 2010)

```
public class MatrixOperation {

    	public static boolean pruefe (int[][] matrix) {

    		//if (){
    		   // return null;

    		//} else {
    			for (int i = 0; i < matrix.length; i++) {

                   for (int j = 0; j < i; j++) {

                       if(matrix[i][j] != 0)
                         return false;
                   }// for j
              } return true; // for i
              //}
    	}

        public static int[] matVek(int[][]matrix, int[]vektor) {

            int ergebnis[][] = new int[][];
            for(int i = 0; i < matrix.length; i++) {
			    for(int j = 0; j < vektor.length-1; j++) {
				    for(int k = 0; k < vektor.length; k++){

					ergebnis[i][j] += array[i][k]*vektor[k][j];
				    }
			    }
            }
        }



    public static void main(String[] args) {


         // Vereinbarungen
	     stdin in = new stdin();
	     int zeilen, spalten;
	     int[][]matrix;
	     int ergebnis[][];
	     int[] vektor;

	     // Eingabe der Anzahl Zeilen + Spalten Matrix
	     System.out.println("Bitte Matrix eingeben\n");
	     zeilen = in.getInt("Wieviele Zeilen hat die Matrix: ");
	     spalten = in.getInt("Wieviele Spalten hat die Matrix: ");

         // Reservierung des Speicherplatzes der Matrix
         matrix = new int[zeilen][spalten];

  	     // Eingabe der Elemente der Matrix
	     for (int i = 0; i<zeilen; i++) {
		     for (int j = 0; j<spalten; j++) {
			     matrix[i][j] = in.getInt("  Eingabe von ["+i+"]["+j+"] ");
		     } // for j
	     } // for i

	     // Eingabe der Anzahl Zeilen + Spalten Vektor
	     System.out.println("Bitte Vektor eingeben\n");
	     zeilen = in.getInt("Wieviele Zeilen hat der Vektor: ");

         // Reservierung des Speicherplatzes des Vektors
         vektor = new int[zeilen];

  	     // Eingabe der Elemente des Vektors
	     for (int i = 0; i<zeilen; i++) {
		      vektor[i] = in.getInt("  Eingabe von ["+i+"]");
		 } // for i




	  System.out.print(" "+ergebnis[i][j]);


    }


}
```

Ich bin zwar noch nicht fertig, aber über zielführende Kritik und verbesserungsvorschläge bin ich dankbar. 

EDIT: @XHelp, danke, problem ist einfach, dass die Aufgabenstellung derart "lose" ist, dass es mir (und auch anderen Kommilitonen) schwer fält zu erkennen welche Form das Programm überhaupt annehmen soll. Die Zwischenergebnisse habe ich gepostet, um zu zeigen wie ich das löse. Der profi sieht da sicher fehler und kann dann rufen, halt, stopp. (passiert nur kaum)

Zur Multiplikation mit einem Vektor, hier mal die Aufgabenstellung:



> Eine Methode int[] matVek(int[][]m, int[]v), die eine Matrix mit einem Vektor
> multipliziert und den Ergebnisvektor zurückgibt. Falls die Multiplikation nicht möglich ist, soll
> die Referenz null zurückgegeben werden.



...tollerweise haben wir die Fehlerbehandlung gerade erst angefangen bzw. nur grob behandelt. Ob und in welcher Form das nun verwendet werden soll hat man uns auch nicht mitgeteilt, aber mit den throwsException bin ich noch nicht firm...


----------



## XHelp (12. Dez 2010)

Selbst in der Aufgabenstellung steht, dass du eine Ergebnis*vektor* hast... Weißt du denn, wie du eine Matrix mit einem Vektor multiplizierst? Genau so wie du es auf dem Papier machst, musst du es auch in Java umsetzen.
Und die Rückgabe von null bezieht sich wohl offensichtlich auch auf die matVek-Methode, deswegen weiß ich nicht so ganz, was es in deiner Prüf-Methode zu suchen hat...


----------



## Jo.Mo. (12. Dez 2010)

Shice...ja das kommt davon wenn man nicht richtig auf die Aufgabenstellung schaut...ich änder es gerade...

Matrix mal Vektor...da habe ich jetzt in einem Java-Schmöker ein beispiel gefunden...


```
public Matrix multiply (Matrix B) {
    		if (this.n != B.getRowDim())
    			throw new IllegalArgumentException ("Matrix-Dimensionen nicht korrekt!");

    		int m = this.getRowDim();
    		int n = B.getColumnDim();
    		double[][] newElems = new double[m][n];
    		double[][] elemsB = B.getArray();
    		double sum = 0;

    		for (int i = 0; i < m; i++) {
    			for (int j = 0; j < n; j++) {
    				sum = 0;
    				for (int k = 0; k < this.getColumnDim(); k++)
    					sum += this.elems[i][k] * elemsB[k][j];
    				newElems[i][j] = sum;
    			}
    		}

    		return new Matrix(m, n, newElems);
        }
```

die bezeichnungen passen zwar nicht, ich probiere gerade zu entschlüssen was die Sachen bewirken und das für meinen Fall abzuändern.


----------

