# Matrizen-Programm



## 4edcjüöä_kopfroller (23. Nov 2015)

Hallo,
meine Aufgabe ist es eine Klasse für Operationen mit Matrizen zu entwerfen (maximale Zeilen- bzw. Spaltenzahl ist 7). Die gespeicherte Matrix soll private sein und über einen Konstruktor erzeugt werden.

Als Public-Methoden der Klasse sollen implementiert werden: Eingabe, Ausgabe, Matrix+Matrix, Matrix*Zahl, Matrix*Matrix und eine Matrix transponieren.

Dies soll in einer kleinen Konsolenanwendung funktionieren. Des Weiteren sollen die eingegeben Matrizen während der Programmabarbeitung intern gespeichert (mindestens zwei), sowie die mehrfache Eingabe der gleichen Matrix vermieden werden.

Meine ConsoleMenu-Klasse sieht im Moment so aus:

```
package de.matrixop;

import java.util.Scanner;

public class ConsoleMenu {

    public static void main(String[] args) {

        boolean ende = false;

        while (!ende) {

            System.out.println("Matrix!\n");
            System.out.println("Bitte wählen Sie welche Berechnung Sie durchführen lassen wollen:\n");
            System.out.println("1. Matrix plus Matrix");
            System.out.println("2. Matrix mal Zahl");
            System.out.println("3. Matrix mal Matrix");
            System.out.println("4. Transponierte Matrix\n");
            System.out.println("0. Programm Benden\n");

            // Menü-Eingabeaufforderung
            Scanner eingabeMenu = new Scanner(System.in);
            int selection = eingabeMenu.nextInt();

            // Menü-Auswahl durch switch-Anweisung
            switch (selection) {
                case 1:
                    Matrix a = new Matrix();
                    a.eingabeDimension();
                    break;
                case 2:
                    break;
                case 3:
                    break;
                case 4:
                    break;
                case 0:
                    ende = true;
                    break;
                default:
                    System.out.println("Falsche Eingabe!");
            }
        }
    }
}
```
Meine im Moment noch sehr halbgare Matrix-Klasse:

```
package de.matrixop;

import java.util.Scanner;

public class Matrix {

    //Instanz-Variablen der Klasse Matrix
    private int dimension;
    private double[][] data;

    // "Matrix"-Konstruktor ohne übergebene Argumente
    Matrix() {
        //this.dimension = dimension;
        //data = new double[dimension][dimension];
    }
    /**
    // "Matrix"-Konstruktor
    private Matrix(int dimension, double[][] data) {

    }**/

    // Getter-Methode dimension
    public int getDimension() {
        return dimension;
    }

    // Setter-Methode dimension
    public void setDimension(int dimension) {
        this.dimension = dimension;
    }

    // Public-Methode für Eingabe der Dimensionen
    public int eingabeDimension() {
        Scanner eingabeDim = new Scanner(System.in);
        System.out.println("Geben Sie bitte die Dimension der Matrix an:");
        int dimension = eingabeDim.nextInt();
        return dimension;
    }

    // Getter-Methode
    public double[][] getData() {
        return data;
    }

    // Setter-Methode
    public void setData(double[][] dat) {
        double[][] data = dat;
    }

    // Public-Methode für Eingabe des Array
    public double[][] eingabeMatrix() {
        Scanner eingabeMat = new Scanner(System.in);
        System.out.println("Geben Sie bitte die Werte der Matrix an:");
        double[][] data = new double[dimension][dimension];
        for (int i = 0; i < dimension; i++)
            for (int j = 0; j < dimension; j++)
                data[i][j] = eingabeMat.nextDouble();
        return data;
    }

    //
    public void ausgabe() {

    }
}
```
(Dass die Klasse Matrix lediglich "dimension" als Instanzvariable hat, liegt daran, dass ich mich der Einfachheit halber auf quadratische Matrizen beschränken möchte - daher keine "nZeilen, mSpalten"-Variablen)

Nun zu meinen Fragen:
Eigentlich hatte ich mir das Programm so vorgestellt, dass der Nutzer - nachdem er eine Auswahl im Menü getroffen hat - immer mit Hilfe einer eingabeDimension-Methode, die Dimension der Matrix eingibt. Anschließend die Werte der Matrix mit Hilfe der eingabeMatrix-Methode.

Da in der Aufgabenstellung von einem Konstrutor für die Matrix die Rede ist, ist das nun schon mein erster Punkt, den ich nicht ganz verstehe. Da ich ohne entsprechendes Objekt (und vorherige Initialisierung), überhaupt gar nicht meine beiden Eingabe-Methoden der Klasse nutzen kann (somit auch gar nicht die Matrix direkt "richtig" mit Werten initialisieren kann), erstelle ich in meiner main-Methode ein Objekt der Klasse Matrix mit einem leeren Konstruktor. Von static-Methoden habe ich bereits gehört, jedoch scheint mir das in meinem Fall auch nicht sinnvoll oder liege ich da falsch?

Wäre es möglich, die eingabeDimension/Matrix-Methoden trotzdem (wie in der Aufgabenstellung gefordert) in der Klasse Matrix zu haben, jedoch eine Matrix direkt mit eingebenen Werten über einen Konstruktor zu erzeugen?


----------



## Dompteur (23. Nov 2015)

4edcjüöä_kopfroller hat gesagt.:


> Da in der Aufgabenstellung von einem Konstrutor für die Matrix die Rede ist, ist das nun schon mein erster Punkt, den ich nicht ganz verstehe. Da ich ohne entsprechendes Objekt (und vorherige Initialisierung), überhaupt gar nicht meine beiden Eingabe-Methoden der Klasse nutzen kann (somit auch gar nicht die Matrix direkt "richtig" mit Werten initialisieren kann), erstelle ich in meiner main-Methode ein Objekt der Klasse Matrix mit einem leeren Konstruktor. Von static-Methoden habe ich bereits gehört, jedoch scheint mir das in meinem Fall auch nicht sinnvoll oder liege ich da falsch?


 
Du kannst das lösen, wenn du in deinem Konstruktor die beiden Methoden eingabeDimension() und eingabeMatrix() aufrufst.

Später einmal wirst du zwar lernen, dass man Modell und User-Interface nicht mischen soll. Aber für deine jetzige Aufgabe sollte dieser Ansatz passen.


----------



## Khal Drogo (23. Nov 2015)

Hallo, wenn du es wirklich so machen willst, wäre folgendes vielleicht eine Möglichkeit:
	
	
	
	





```
// Pseudocode
// Main
Matrix m = new Matrix();

// Matrix
public Matrix() {
  int dimension = getDimensionFromUser();
  double matrix[][] = new double[dimension][dimension];
  fillMatrix();
}
```

Mit freundlichen Grüßen
Xelsarion

EDIT: Da war @Dompteur schneller


----------



## 4edcjüöä_kopfroller (23. Nov 2015)

Oh, super! Vielen Dank für eure schnellen Antworten. Jetzt fühle ich mich schon ein gutes Stück weiter.


----------



## strußi (23. Nov 2015)

irgendwo/-wann habe ich mal eine Klasse mit den ganzen Matrix und Vektor-Operationen gepostet ;-) wenn du Zeit in die suche investierst, kannst du sie finden.

Ich erinnere mich dunkel, das so etwas schon einmal gefragt wurde.

thread 
Matrix mit Vektor multiplizieren


----------



## 4edcjüöä_kopfroller (23. Nov 2015)

Mein Konstruktor sieht nun wie folgt aus:

```
// Matrix-Konstruktor
    Matrix() {
        int dimension = getDimensionFromUser();
        double[][] data = getMatrixFromUser();
    }
```
Die Dimension-Eingabe funktioniert, allerdings bin ich mir bei meiner Matrix-Eingabe-Methode nicht mehr ganz so sicher:


```
// Public-Methode für Eingabe des Array
    public double[][] getMatrixFromUser() {
        Scanner eingabeMat = new Scanner(System.in);
        System.out.println("Geben Sie bitte die Werte der Matrix an:");
        double[][] data = new double[getDimension()][getDimension()];
        for (int i = 0; i < dimension; i++)
            for (int j = 0; j < dimension; j++)
                data[i][j] = eingabeMat.nextDouble();
        return data;
    }
```

Macht die Zeile "double[][] data = new double[getDimension()][getDimension()];
überhaupt Sinn? Hier mit möchte ich die zuvor eingegebene dimension-Variable abrufen, dies scheint allerdings nicht so recht zu funktionieren. Edit: Wobei es mir auch nicht richtig erscheint, dies mit einer Getter-Methode zu tun.

Zweitens: Bin ich richtig in der Annahme, dass ich so etwas wie eine "fillMatrix"- zusätzlich zu meiner "getMatrixFromUser"-Methode brauchen werde?


----------



## Dompteur (23. Nov 2015)

Dir fehlt eine Zuweisung auf deine Instanz-Variablen. Du verwendest überall lokale Methodenvariable.
Um deine Instanzvariablen zu initialisieren, sollte dein Konstruktor so aussehen:

```
Matrix() {
         dimension = getDimensionFromUser();
         data = getMatrixFromUser();
     }
```
 
"getMatrixFromUser()" sollte dann so funktionieren. "getDimension()" ist schon in Ordnung. Das Problem war, dass die Instanzvariable nie gesetzt wurde und daher den Wert 0 hatte.


----------



## 4edcjüöä_kopfroller (23. Nov 2015)

Dompteur hat gesagt.:


> Dir fehlt eine Zuweisung auf deine Instanz-Variablen. Du verwendest überall lokale Methodenvariable.
> Um deine Instanzvariablen zu initialisieren, sollte dein Konstruktor so aussehen:
> 
> ```
> ...


Danke, die Eingabe von Dimension- und Matrix-Werten funktioniert nun. 

Zu den Berechnungen habe ich nun folgende Frage:
Meine Berechnungs-Methode für "Matrix+Matrix" sieht so aus:

```
public static double[][] berechneMatrixPlusMatrix(double[][] a, double[][] b) {
        double[][] c = new double [a.length][a[0].length];
        for (int i = 0; i < a.length; i++)
            for (int j = 0; j < b.length; j++)  {
                c[i][j] = a[i][j] + b[i][j];
            }
        return c;
    }
```
Diese möchte ich über die main-Methode wie folgt aufrufen:

```
case 1:
                    Matrix m = new Matrix();
                    Matrix n = new Matrix();
                    Matrix.berechneMatrixPlusMatrix(m.getData(), n.getData());
                    break;
```
Grundsätzlich ist meine Idee, dass ich die zuvor erzeugten Array-Daten von m und n an die Methode berechneMatrixPlusMatrix übergeben möchte. Liegt das Problem an der Art und Weise wie ich die Arrays übergeben will?


----------



## Dompteur (23. Nov 2015)

So wie du das machst, liefert deine Methode berechneMatrixPlusMatrix() ein Ergebnis, das du nicht weiterverwendest.
Versuche das einmal. ausgabe() sollte natürlich schon vorhanden sein.

```
Matrix sum = Matrix.berechneMatrixPlusMatrix(m.getData(), n.getData());
sum.ausgabe();
```


----------



## 4edcjüöä_kopfroller (23. Nov 2015)

Dompteur hat gesagt.:


> So wie du das machst, liefert deine Methode berechneMatrixPlusMatrix() ein Ergebnis, das du nicht weiterverwendest.
> Versuche das einmal. ausgabe() sollte natürlich schon vorhanden sein.
> 
> ```
> ...




```
public void ausgabe() {
        System.out.println("Die Ergebnis-Matrix lautet:\n");
        for (int i = 0; i < dimension; i++)
            for (int j = 0; j < dimension; j ++)
                System.out.println(data[i][j]);
    }

    public static double[][] berechneMatrixPlusMatrix(double[][] a, double[][] b) {
        double[][] c = new double [a.length][a[0].length];
        for (int i = 0; i < a.length; i++)
            for (int j = 0; j < b.length; j++)  {
                c[i][j] = a[i][j] + b[i][j];
            }
        return c;
    }
```
main:

```
case 1:
                    Matrix m = new Matrix();
                    Matrix n = new Matrix();
                    Matrix sum = Matrix.berechneMatrixPlusMatrix(m.getData(), n.getData());
                    sum.ausgabe();
```

Allerdings meckert meine IDE bei der Zeile

```
Matrix sum = Matrix.berechneMatrixPlusMatrix(m.getData(), n.getData());
```
"Incompatible Types. Required: de.matrixop.Matrix. Found: double[][]"

Edit: Wahrscheinlich muss ich in der berechneMatrixPlusMatrix Methode noch direkt ein Matrix-Objekt erzeugen lassen oder? Bzw. wie lasse ich den Computer wissen, dass die Berechnung in berechneMatrixPlusMatrix auch eine Matrix ausspuckt? ...vielleicht muss er das auch gar nicht wissen sondern lediglich den Array dann anschließend mit Hilfe der ausgabe-Methode ausgeben?


----------



## strußi (23. Nov 2015)

du erhälst von der methode einen double[][] zurück und willst den in ein Objekt vom Typ Matrix stopfen, das geht nicht
du kannst einen weiteren Konstruktor machen der double[][] als parameter entgegen nimmt.
//so ähnlich sollte das in deiner klasse stehen
public Matrix ( double[][] matrix){
this.matrix =matrix;
}

dann kannst du Matrix erg = new Matrix( berechneMatrixPlusMatrix(m.getData(), n.getData())); aufrufen



4edcjüöä_kopfroller hat gesagt.:


> *public* *void* ausgabe() {
> System.out.println("Die Ergebnis-Matrix lautet:*\n*");
> *for* (*int* i = 0; i < dimension; i++)
> *for* (*int* j = 0; j < dimension; j ++)
> ...



sollte so aussehen
System.out.println("Die Ergebnis-Matrix lautet:*\n*");
*for* (*int* i = 0; i < dimension; i++)
*for* (*int* j = 0; j < dimension; j ++)
System.out.print(data[i][j] +" ");
    }
    System.out.println("");
}
sonst gibst du jeden matrixwert in einer neuen Zeile aus


----------



## 4edcjüöä_kopfroller (23. Nov 2015)

```
public void ausgabe() {
        System.out.println("Die Ergebnis-Matrix lautet:\n");
        for (int i = 0; i < dimension; i++)
            for (int j = 0; j < dimension; j ++)
                System.out.print(data[i][j] +" ");
        System.out.println("");
    }
```
Funktioniert nun alles, bis auf die Tatsache, dass die ausgabe-Methode nichts ausgibt.
Meine main-Methode:

```
case 1:
                    Matrix m = new Matrix();
                    Matrix n = new Matrix();
                    Matrix sum = new Matrix(Matrix.berechneMatrixPlusMatrix(m.getData(), n.getData()));
                    sum.ausgabe();
                    break;
```
Matrix-Konstruktor #2

```
Matrix(double[][] data) {
        this.data = data;
        //this.dimension = dimension;
    }
```
Hat das sum-Matrix-Objekt denn überhaupt ein Wissen davon, welche dimension es hat?

Edit:

```
public void ausgabe() {
        System.out.println("Die Ergebnis-Matrix lautet:\n");
        for (int i = 0; i < data.length; i++)
            for (int j = 0; j < data.length; j ++)
                System.out.print(data[i][j] +" ");
        System.out.println("");
    }
```
Gibt schon mal etwas aus. 
"2.0 4.0 6.0 8.0" der Zeilenumbruch scheint nicht zu funktionieren.


----------



## 4edcjüöä_kopfroller (23. Nov 2015)

Sorry, für den Doppelpost, aber editieren nach 30 Minuten funktioniert hier leider nicht.
Meine Ausgabe-Methode sieht nun so aus und tut was sie soll:

```
public void ausgabe() {
        System.out.println();
        for(int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[0].length; j++)
                System.out.printf("%5.2f ", data[i][j]);
            System.out.println();
        }
    }
```


----------



## strußi (23. Nov 2015)

fuer eine bessere Lesbarkeit, setzte bitte alle Klammer, auch die geschweiften.


----------



## 4edcjüöä_kopfroller (24. Nov 2015)

Guten Morgen, ein paar Fragen habe ich noch in petto 

Meine MatrixTransponieren-Methode funktioniert nicht so wie sie soll.

```
// Matrix transponieren
    public static double[][] getTransponierteMatrix(double a[][]) {
        double[][] c = new double[a[0].length][a.length];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[0].length; j++) {
                c[j][i] = a[i][j];
            }
        }
        return c;
    }
```
Aus meiner main-Methode rufe ich sie wie folgt auf:

```
case 4:
                    Matrix t = new Matrix();
                    Matrix mt = new Matrix(Matrix.getTransponierteMatrix(t.getData()));
                    mt.ausgabe();
                    break;
```

Edit: So scheint das ganze nun auch zu funktionieren

```
// Matrix transponieren
    public static double[][] getTransponierteMatrix(double a[][]) {
        double[][] c = new double[a[0].length][a.length];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[i].length; j++) {
                c[j][i] = a[i][j];
            }
        }
        return c;
    }
```

Wie könnte ich zudem noch eine Überprüfung einbauen, ob die eingegebene Dimension der Matrix wirklich nicht höher als 7 ist?

```
// Public-Methode für Eingabe des Matrix-Array
    public double[][] getMatrixFromUser() {
        Scanner inputMat = new Scanner(System.in);
        System.out.println("Geben Sie bitte die Werte der Matrix an:");
        double[][] data = new double[getDimension()][getDimension()];
        for (int i = 0; i < dimension; i++) {
            for (int j = 0; j < dimension; j++) {
                data[i][j] = inputMat.nextDouble();
            }
        }
        return data;
    }
```
Könnte ich die den gesamten inneren Block nicht in einfach in eine Schleife packen?


----------



## Khal Drogo (24. Nov 2015)

```
do {
  dimension = input;
} while(dimension < 0 || dimension > 7); // ?
```

Mit freundlichen Grüßen
Xelsarion


----------



## 4edcjüöä_kopfroller (24. Nov 2015)

Danke dir. Der Vollständigkeit halber noch mal alles zusammen:


Spoiler: ConsoleMenu.java





```
package de.matrixop;

import java.util.Scanner;


public class ConsoleMenu {

    public static void main(String[] args) {

        boolean ende = false;

        while (!ende) {

            System.out.println("\n");
            System.out.println("Bitte wählen Sie welche Berechnung Sie durchführen lassen wollen:\n");
            System.out.println("1. Matrix plus Matrix");
            System.out.println("2. Matrix mal Zahl");
            System.out.println("3. Matrix mal Matrix");
            System.out.println("4. Transponierte Matrix\n");
            System.out.println("0. Programm Benden\n");

            // Menü-Eingabeaufforderung
            Scanner inputMenu = new Scanner(System.in);
            int selection = inputMenu.nextInt();

            // Menü-Auswahl durch switch-Anweisung
            switch (selection) {
                case 1:
                    Matrix m = new Matrix();
                    Matrix n = new Matrix();
                    Matrix sum = new Matrix(Matrix.getMatrixPlusMatrix(m.getData(), n.getData()));
                    sum.ausgabe();
                    break;
                case 2:
                    Matrix p = new Matrix();
                    Scanner inputFakt = new Scanner(System.in);
                    System.out.println("Geben Sie bitte den Faktor für die Multiplikation an:");
                    int faktor = inputFakt.nextInt();
                    Matrix multmz = new Matrix(Matrix.getMatrixMalZahl(p.getData(), faktor));
                    multmz.ausgabe();
                    break;
                case 3:
                    Matrix x = new Matrix();
                    Matrix y = new Matrix();
                    Matrix multmm = new Matrix(Matrix.getMatrixMalMatrix(x.getData(), y.getData()));
                    multmm.ausgabe();
                    break;
                case 4:
                    Matrix t = new Matrix();
                    Matrix mt = new Matrix(Matrix.getTransponierteMatrix(t.getData()));
                    mt.ausgabe();
                    break;
                case 0:
                    ende = true;
                    break;
                default:
                    System.out.println("Falsche Eingabe!");
            }
        }
    }
}
```






Spoiler: Matrix.java





```
package de.matrixop;

import java.util.Scanner;

public class Matrix {

    //Instanz-Variablen der Klasse Matrix
    private int dimension;
    private double[][] data;

    // Matrix-Konstruktor
    Matrix() {
        dimension = getDimensionFromUser();
        data = getMatrixFromUser();
    }

    // Matrix-Konstruktor dem als Argument eine Ergebnis-Matrix übergeben wird
    Matrix(double[][] data) {
        this.data = data;
    }

    // Getter-Methode dimension
    public int getDimension() {
        return dimension;
    }

    // Setter-Methode dimension
    public void setDimension(int dimension) {
        this.dimension = dimension;
    }


    // Getter-Methode für Inhalt der Matrix
    public double[][] getData() {
        return data;
    }

    // Setter-Methode für Inhalt der Matrix
    public void setData(double[][] dat) {
        double[][] data = dat;
    }

    // Public-Methode für Eingabe der Dimensionen
    public int getDimensionFromUser() {
        Scanner inputDim = new Scanner(System.in);
        System.out.println("Geben Sie bitte die Dimension der Matrix an:");
        int dimension = inputDim.nextInt();
        return dimension;
    }

    // Public-Methode für Eingabe des Matrix-Array
    public double[][] getMatrixFromUser() {
        Scanner inputMat = new Scanner(System.in);
        System.out.println("Geben Sie bitte die Werte der Matrix an:");
        double[][] data = new double[getDimension()][getDimension()];
        for (int i = 0; i < dimension; i++) {
            for (int j = 0; j < dimension; j++) {
                data[i][j] = inputMat.nextDouble();
            }
        }
        return data;
    }

    // Ausgabe-Methode für Ergebnis-Matrix
    public void ausgabe() {
        System.out.println("Die Ergebnis-Matrix lautet:");
        System.out.println();
        for(int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[0].length; j++) {
                System.out.printf("%5.2f ", data[i][j]);
            }
            System.out.println();
        }
    }

    //Methode zur Berechnung von Matrix + Matrix
    public static double[][] getMatrixPlusMatrix(double[][] a, double[][] b) {
        double[][] c = new double [a.length][a[0].length];
        for (int i = 0; i < a.length; i++)
            for (int j = 0; j < b.length; j++)  {
                c[i][j] = a[i][j] + b[i][j];
            }
        return c;
    }

    //Multiplikation von Matrix mit gewählter Zahl
    public static double[][] getMatrixMalZahl(double[][] a, int faktor) {
        double[][] c = new double[a.length][a.length];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a.length; j++) {
                c[i][j] = a[i][j] * faktor;
            }
        }
        return c;
    }

    // Multiplikation von Matrix und Matrix
    public static double[][] getMatrixMalMatrix(double a[][], double b[][]) {
        double[][] c = new double[a.length][b.length];
        for (int i = 0; i < a.length; i++)
            for (int j = 0; j < b.length; j++)  {
                double summe = 0;
                for (int k = 0; k < b.length; k++) {
                    summe += a[i][k] * b[k][j];
                }
            c[i][j] = summe;
            }
        return c;
    }

    // Matrix transponieren
    public static double[][] getTransponierteMatrix(double a[][]) {
        double[][] c = new double[a[0].length][a.length];
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[i].length; j++) {
                c[j][i] = a[i][j];
            }
        }
        return c;
    }

}
```



Was ich mich gestern auch noch gefragt habe: Ist es denn guter (OOP-)Stil Setter- und Getter-Methoden innerhalb der eigenen Klasse bspw. in Methoden zu nutzen? Oder sind sie nicht doch eher nur für den Zugriff aus anderen Klasse da?


----------



## Khal Drogo (24. Nov 2015)

Eigentlich benutzt man innerhalb der entsprechenden Klasse keine Getter oder Setter, die sind für den Zugriff von außerhalb gedacht (und nötig). Warum solltest du den Umweg nehmen, wenn du auch direkt zum Ziel kannst 

Mit freundlichen Grüßen
Xelsarion


----------

