Methoden Matrix als 1D Array mit Werten füllen

VM

Mitglied
Hallo Leute,

ich bin zum Ersten mal hier unterwegs, daher erst ein mal vielen Dank, dass es so eine Möglichkeit gibt :applaus::toll:

Nun hoffe ich, dass mir geholfen werden kann. 😕

Mein Problem ist eine Getter Methode für ein 1D Array, in welchem werte einer Matrix gespeichert werden, die nur Einträge auf der Hauptdiagonalen und x Nebendiagonalen hat (Bandmatrix).
Ich habe lange überlegt und leider keine Lösung gefunden, die sich universell anwenden lässt..
Im wesentliche versuche ich über die Spalten-/Zeileneingabe des Benutzers die Position im Feld zu ermitteln. Die klappt leider nur für den sehr simplen Fall, dass es sich um ein Hauptdiagonalen Element handelt, da diese den ersten Block im Array darstellt.

Hier mein Konstruktor für der/die/das ???:L 1D Array
Java:
/**
 * Konstruktor zur Erstellung einer symmetrischen Band-Matrix
 * Band Matrix wird als 1D-Feld, i welchem nur die Hauptdiagonale
 * und die unteren Bandbreiten-Elemten dargestellt werden, um Speicherplatz zu sparen
 * @param dim = Dimension der Matrix 
 */
public SymmetrischeBandMatrix(int dim,short bandbreite1)throws Ausnahme{
	// Ausnahmen für Bandbreite größer als Dimension der Matrix
	if (bandbreite1 > dim){
		throw new Ausnahme("Die Bandbreite übersteigt die Dimension der Matrix");
	}
	//Hilfsvariable um rekursive Folge mit Schleife darzustellen
	int laenge=0; 
	this.dim=dim;
	// Schleife um rekursive Folge darzustellen 
	for (int i=0; i<bandbreite1;i++){
		laenge += (dim-i);
	}
	// Feld mit der Laenge laenge wird erzeugt
	this.matrix1D=new double [laenge];
	}

Hier mein bisheriger Code für die Methode

Java:
ublic double getKoeffizient1D(int n,int m){
	// wenn n=m wird auf Element der Hauptdiagonalen zugegriffen
	if (n==m){
		return matrix1D[n];
	}
	// Schleife mit Start index 1
	for (int i=1; i<bandbreite1;i++)
       {
//i läuft bis zur Bandbreite
	if (n==m+i){
		return matrix1D[];//Stelle??! dim + dim -1 + dim -2 .... + m? 
	}
	if (n==m+1){
		return matrix1D[dim+m];
	}

	}

Wie man sieht klappt es händisch für n=m und n=m+1.
Eine Idee von mir war darauf zu spekulieren, dass der Benutzer nur Matrizen mit einer Dimension übergibt, die ich zuvor händisch möglich gemacht habe.:bloed: :bloed: :bloed:
Ziemlich dämlicher Ansatz, mit viel zu viel Arbeit.

:idea: Jetzt habe ich mir gedacht, dass ich einfach immer ans Ende eines Blocks laufe und dann wieder zurück zu dem Element, dass ich haben will.
Beispiel: Benutzer will den Wert an der Stelle 3,5 (Zeile(n),Spalte(m)).
Die Schleife stellt fest, dass n=m+2 ist. Jetzt müsste man in den 2. Block gehen.

Ansatz: Dimension(Anzahl Elemente auf Hauptdiagonalen)= dim

dim + dim-1 + dim-2 (nun stehe ich am Ende der Elemente der 2. Diagonalen) - (dim-2-m)
(jetzt sollte ich eigentlich am gewünschten Element stehen.)

Nur leider weiß ich nicht wie ich das als Schleife ausdrücken kann...


Daher wende ich mich hoffnungsvoll an euch.

Liebe Grüße
 
Warum bildest du eine zweidimensionale Struktur eindimensional ab?
Ich habe nicht ganz verstanden, wie du die Matrix speicherst.
Wenn es denn unbedingt eindimensional sein muss, würde ich es so machen:
Code:
1  2  3  4  5
6  7  8  9  10
11 12 13 14 15 = m5x5       Zahl in Matrix - 1 = Index im 1D Array
16 17 18 19 20
21 22 23 24 25

Die einzelnen Werte im 1D Array kannst du dann so ansprechen:
Code:
index = ((zeile - 1) * spaltenzahl + spalte) - 1
 
Zuletzt bearbeitet:
hey,

das klappt leider nicht.

Ich hau ja nur die Diagonalen mit Werten in das Array..


Ist ein 1D Feld nicht günstiger als ein 2D Feld, im Bezug auf den verbrauchten Speicher?
 
Zuletzt bearbeitet:
Ist ein 1D Feld nicht günstiger als ein 2D Feld, im Bezug auf den verbrauchten Speicher?


Also heutzutage sollte man sich um Speicher keine großen Sorgen machen! Diese Probleme kommen erst bei größeren Projekten, wo man vielleicht wirklich etwas speicherlastiges machen will.
Daher kannst du es ruhig als 2D Array abbilden.

Bzw. in Zukunft so programmieren wie es einfach logisch ist, sollte es dann Speicherprobleme geben kann man diese dann(!) immer noch lösen.
Also nicht davor schon Probleme beheben die nicht auftauchen müssen. Natürlich ist es Vorteilhaft wenn man weiß man könnte hier oder dort Probleme bekommen und das oder dies wären vielleicht mögliche Lösungen, aber diese sollten auch erst eingebaut werden wenn es zwingend wird!
 
Ok 🙂

Danke für den Tipp 🙂

Ich frage mich grad wie ich am besten den Speicherbedarf berechne...
Es gilt ja: Maximale Datenmenge einer Double ist 64 bit.
Ist es dann (Bsp. 5x5 Matrix): 5*64bit + 5*64bit = 640 bist = 80 Bytes?



Wenn ich es als 2D-Feld auffasse, sieht mein Code wie folgt aus:

Java:
**
 * Konstruktor zur Erstellung einer symmetrischen Band-Matrix
 * Es werden nur die Hauptdiagonale, sowie die restlichen Bandbreiten-Elemten in einem double 2D-Feld gespeichert
 * Die Symmetrischen Einträge werden durch Getter / Setter Methoden simmuliert
 * @param dim = Dimension der Matrix
 */
public SymmetrischeBandMatrix(int dim, int bandbreite2)throws Ausnahme{
	if (bandbreite2 > dim){
		throw new Ausnahme ("Die Bandbreite übersteigt die Dimension der Matrix");
	}
this.dim=dim;
this.matrix2D=new double [dim][];
for (int i=0;i<bandbreite2;i++){
	matrix2D[i]=new double [dim-i];
	
}
}


/**
 * Getter Mehtode für 2D-Matrix Variante 
 * mit Zugriffsvertauschung bei Zugriff auf Elemente der Bandbreite außerhalb der unteren Dreiecksmatrix
 * Es werden keine Ausnahmen geworfen, da etwaige Fehler in der Setter-Methode behandelt werden
 */
public double getKoeffizient2D(int n, int m){
	if (n<m){
		int y = n;
		n = m;
		m = y;
		
	}
	
return matrix2D[n][m];	
}

/**
 * Setter Mehtode für 2D-Matrix Variante
 * wirft Ausnahme, falls auf ein Feld außerhalb der Matrix-Dimension zugegriffen werden soll
 */
public void setKoeffizient2D(int n, int m,double koeffizient)throws Ausnahme{
	// wirft Ausnahme falls Spalten oder Zeilenrang überschritten wird
	if (n+1 > bandbreite2 || m+1>bandbreite2){throw new Ausnahme("Einer oder mehrere der gesetzten Werte befinden sich außerhalb der Matrix-Dimension"); 
	}
	if (n<m){
	int y = n;
	n = m;
	m = y;
}
	matrix2D[n][m]= koeffizient;
}

Vielen Dank 🙂
 
Ich frage mich grad wie ich am besten den Speicherbedarf berechne...
Es gilt ja: Maximale Datenmenge einer Double ist 64 bit.
Ist es dann (Bsp. 5x5 Matrix): 5*64bit + 5*64bit = 640 bist = 80 Bytes?

Hm viele Einträge passen in ein 5x5 Feld? 😉
Hier hat sich ein kleiner Fehler eingeschlichen bei dir.
Und desweiteren werden ja nicht nur die X Double gespeichert sondern noch vom Objekt der eine oder andere Overhead.
Wie gesagt um Speicher keine Sorgen machen, solange du nicht z.B. mehrere GB große Dateien parallel verarbeiten willst oä.
 
Hilf dir der Ansatz hier?
Java:
public double getKoeffizient2D(int n, int m){
    if (n<m) return getKoeffizient2D(m, n);
    int positionInDiagonale = m;
    int nrDiagonale = n-m; //0 = Hauptdiagonale, 1 = erste Nebendiagonale usw.
}
 
@Joose
Hm viele Einträge passen in ein 5x5 Feld?
5*5 = 25 Einträge
daraus folgt dann 25*64 bit = 200 bytes?

Kann ich das was im Overhead drin ist, irgendwie abschätzen?

Danke 🙂

@DrZoidberg
Hilft dir der Ansatz hier?

Erst einmal ist es gut zu wissen, dass ich als return auch eine Methode benutzen kann. An sich ist das auch einleuchtet, jetzt wo ich es weiß 🙂

Der Ansatz ist interessant, er hilft mir auf jeden Fall meine Schleife aus der Methode löschen zu können, da ich so einfacher an einen Wert kommen, mit dem ich sogar weiter rechnen kann 🙂
Ich hab aus dem Ansatz folgendes gebastelt:
Java:
public double GetKoeffizient1D(int n,int m){
	if (n<m){ return getKoeffizient2D(m, n);
	}
    int positionInDiagonale = m;
    int nrDiagonale = n-m; //0 = Hauptdiagonale, 1 = erste Nebendiagonale usw.
    int positionArray=0;
    for (int i=1;i<nrDiagonale;i++){
    positionArray += (dim-i-1); 
    		}
return matrix1D[(positionArray+positionInDiagonale)];
}

jetzt bastle ich mal weiter an der Anwendung, dann kann ich auch überprüfen, ob die gewünschten Ergebnisse geliefert werden 🙂

Vielen Dank für eure Hilfe!!!:applaus:
 
Eine Möglichkeit zum Abschätzen wäre die, dass du guckst, wie viel Speicher die JVM belegt, dann ein Array erzeugst und dann wieder nachguckst.
 
Die Schleife die ich oben bastelt habe kann nicht funktionieren....

hier ist die, die zumindest auf dem Papier funktioniert 🙂

Java:
public double getKoeffizient1D(int n,int m){
	if (n<m){ return getKoeffizient1D(m, n);
	}
	 if (n==m){
	    	return matrix1D[n];
	    }
	 
    int positionInDiagonale = m;
    int nrDiagonale = n-m; //0 = Hauptdiagonale, 1 = erste Nebendiagonale usw.
    int positionArray=0;
   
    for (int i=0;i<nrDiagonale;i++){
    positionArray += (dim-i); 
    		}
return matrix1D[(positionArray+positionInDiagonale)];
}
	
}

@Gucky:
du guckst, wie viel Speicher die JVM belegt

gibt es dafür ein Tool, oder muss ich das aus dem Taskmanager/Aktivitätsanzeige auslesen?



Liebe Grüße und Danke an alle 🙂 🙂 🙂
 
Mit
Java:
Runtime rt = Runtime.getRuntime();
rt.gc(); //Bereinigung
System.out.println(rt.totalMemory() - rt.freeMemory()); //Ausgeben
bereinigst du den Speicher und gibst den aktuell belegten Speicher aus.

Der Unterschied zwischen dem ein- und dem zweidimensionalen Array wird gewaltig aussehen, da erstens beide Werte in Bytes ausgegeben werden und zum Zweiten ein 5x5 2D Array aus insgesamt 6 Arrays besteht. Aber dann musst du dir mal überlegen, wie viel das in Wirklichkeit ist. Nämlich nix 😉
 
Zuletzt bearbeitet:

Zurück
Oben