1 Prof. Dr. Th. Letschert OOP Aufgabenblatt 11 3. Januar 2014 Aufgabe 1 Widerstände, deren elektrischer Widerstand im Gleichstromkreis genauso groß ist wie im Wechselstromkreis, nennt man ohmsche Widerstände. Beispielsweise sind Drähte ohmsche Widerstände. Der Widerstand R eines Drahts kann berechnet aus der Länge l, dem Querschnitt A und dem spezifischen Widerstand ρ des Materials: R = ρ ∗ i/A Drahtwiderstände treten meist in Form einer Spule auf. Die elektrotechnischen Details interessieren hier aber nicht weiter. Wir nehmen an, dass ein ohmscher Widerstand egal welcher Bauart durch seinen Widerstandswert in Ohm gegeben ist: package oop.blatt_11.aufgabe_1; /** * Instanzen dieser Klasse modellieren Bauteile mit einem ohmschen Widerstand. */ public class Widerstand { private double r; // Widerstandswert in Ohm /** * Initialisiert das Bauteil mit seinem Widerstand. * @param ohm Widerstand in Ohm */ public Widerstand(double ohm) { this.r = ohm; } /** * Liefert den Widerstand des Bauteils. * * @return Widerstand in Ohm */ public double getR() { return r; } } Widerstände können in Reihe geschaltet werden. Das ergibt eine Reihenschaltung. Eine Reihenschaltung mit einen Widerstand, der der Summe der der zusammen geschalteten Widerstände entspricht: /** * Instanzen dieser Klasse modellieren Reihenschaltungen ohmscher Widerstaende. */ public class Reihenschaltung { private Widerstand w1; private Widerstand w2; /** * Initilaisiert Reihenschaltung aus zwei Widerstaenden. * @param w1 2 * @param w2 */ public Reihenschaltung(Widerstand w1, Widerstand w2) { this.w1 = w1; this.w2 = w2; } /** * Liefert den ohmschen Widerstand der in Reihe geschalteten Widerstaende. * @return Gesamtwiderstand der Schaltung. */ public double getR() { return w1.getR()+w2.getR(); } } Widerstände können auch parallel geschaltet werden. Eine Parallelschaltung von Widerständen hat auch wieder einen Widerstand. Dieser ergibt sich aus der Beziehung 1 1 1 = + R R1 R2 R ist dabei der Gesamtwiderstand, R1 und R2 sind die parallel geschalteten Widerstände. Erweitern Sie die Definitionen um eine der Klasse Parallelschaltung entsprechende Klasse Reihenschaltung zu Modellierung von Parallelschaltungen. Folgende Anweisungen sollten damit ausführbar sein: Widerstand r1 = new Widerstand(50); Widerstand r2 = new Widerstand(100); Reihenschaltung c1 = new Reihenschaltung(r1, r2); Parallelschaltung c2 = new Parallelschaltung(r1, r2); System.out.println(c1.getR()); System.out.println(c2.getR()); Die Ausgabe sollte zeigen, dass die beiden Schaltungen einen Widerstand von 150 Ω bzw. 100/3 Ω haben. Aufgabe 2 An Ihre drei Arten von Schaltkreisen – Widerstand, Reihenschaltung, Parallelschaltung – soll nun eine Spannung angelegt werden und wir wollen den Stromfluss beobachten. Das Ohmsche Gesetz beschreibt den Zusammenhang zwischen Widerstand R, Stromfluss I und Spannung U : I= U R Die Klasse, die einen Ohmschen Widerstand modelliert, kann erweitert werden zu: package oop.blatt_11.aufgabe_2; /** * Instanzen dieser Klasse modellieren Bauteile mit Ohmschem Widerstand. */ public class Widerstand { private double r; // Widerstandswert in Ohm private double u; // Aktuell angelegte Spannung in Volt 3 /** * Initialisiert Bauteil mit seinem Widerstand. * @param ohm Widerstand in Ohm */ public Widerstand(double ohm) { this.r = ohm; } /** * Liefert den Widerstand des Bauteils. * @return Widerstand des Bauteils */ public double getR() { return r; } /** * Modelliert das Anlegen einer Spannung. * @param u die angelegte Spannung */ public void setU(double u) { this.u = u; } /** * Modelliert den aktuellen Stromfluss. * @return Stromfluss bei aktuell angelegter Spannung */ public double getI() { return u/r; } } Erweitern Sie auch die Definitionen der Klassen zur Modellierung von Reihen- und Parallelschaltungen derart, dass das Anlegen einer Spannung an einen Schaltkreis und das anschließende Messen eines Stromflusses modelliert werden kann und damit folgender Code ausführbar wird und 0.3333333333333333 und 2.4 ausgibt. Widerstand r1 = new Widerstand(50); Widerstand r2 = new Widerstand(100); Reihenschaltung c1 = new Reihenschaltung(r1, r2); Parallelschaltung c2 = new Parallelschaltung(r1, r2); c1.setU(50.0); c2.setU(80.0); System.out.println(c1.getI()); System.out.println(c2.getI()); Aufgabe 3 In den Aufgaben 1 und 2 haben Sie Schaltkreise mit Widerständen, Reihenschaltungen oder Parallelschaltungen modelliert. In den Modellen kann der Stromfluss bei angelegten Spannungen berechnet werden. Damit können Schaltkreise aus Widerständen und Parallel– und Reihenschaltungen modelliert werden. Genauer gesagt können drei Arten von Schaltkreise modelliert werden: • Schaltkreise die aus einem Widerstand bestehen. • Schaltkreise die aus zwei in Reihe geschalteten Widerständen bestehen. 4 • Schaltkreise die aus zwei parallel geschalteten Widerständen bestehen. Das ist sehr unbefriedigend. Eigentlich müssten sich Reihen– und Parallelschaltungen selbst wieder zu neuen Schaltungen verknüpfen lassen. Also beispielsweise: Widerstand Widerstand Widerstand Widerstand r1 r2 r3 r4 = = = = new new new new Widerstand(50); Widerstand(100); Widerstand(150); Widerstand(300); Reihenschaltung sr1 = new Reihenschaltung(r1, r2); Reihenschaltung sr2 = new Reihenschaltung(r3, r4); Parallelschaltung sp = new Parallelschaltung(sr1, sr2); Warum funktioniert das nicht? Hmm – vielleicht, weil Parallelschaltung keinen entsprechenden Konstruktor hat. Erstellen wir einen passenden Konstruktor. Beispielsweise als: private Widerstand w1; private Widerstand w2; private double u = 0.0; // Spannung in Volt private Reihenschaltung sr1; // neu private Reihenschaltung sr2; // neu public Parallelschaltung(Widerstand w1, Widerstand w2) { this.w1 = w1; this.w2 = w2; } // neu: public Parallelschaltung(Reihenschaltung sr1, Reihenschaltung sr2) { this.sr1 = sr1; this.sr2 =sr2; } Dann brauchen wir noch einen Konstruktor, der es uns erlaubt eine Reihenschaltung und einen Widerstand parallel zu schalten, und einen der uns erlaubt Eine Reihenschaltung und eine Parallelschaltung parallel zu schalten und einen .... Das ist alles furchtbar. Irgendetwas haben wir falsch gemacht. Aber was? Nun, wir haben mit Widerstand eine Klasse definiert, die ein irgendwie geartetes Ding modelliert, das einen Widerstand hat. Das ist aber nicht präzise genug. Wir haben zwei Dinge vermischt: • Widerstände als elementare elektronische Bauelemente. • Widerstände als etwas das einen Widerstand hat. Zu einem Schaltkreis verschalten kann man alles was einen Widerstand hat: Elementare Bauelemente und Schaltkreise. Beides ist eng verwandt aber nicht das gleiche. Einer der beiden Begriffe ist allgemeiner, umfassender als der andere. Welcher? 1. Welches Java–Konstrukt kann uns uns dabei helfen, Arten von Dinge und Klassen von Dingen mit bestimmten Eigenschaften zu unterscheiden und damit die Sache in vernünftiger Form zu bringen? 2. Unterscheiden Sie Widerstände als elementare Bauelemente und Widerstände als “Dinge mit einem Widerstand” und konzipieren Sie eine entsprechende Lösung als Klassendiagramm in UML. 5 Aufgabe 4 Wir unterscheiden Widerstände als elementare Bauelemente und Widerstände als “Ding mit einem Widerstand”. Der Einfachheit halber nehmen wir als elementares Bauelement mit Widerstand eine Spule (wir haben es nur mit Gleichstrom zu tun). Wir benennen die Klasse Widerstand um in Spule: package oop.blatt_11.aufgabe_4; /** * Instanzen dieser Klasse modellieren Spulen mit Ohmschem Widerstand. */ public class Spule { private double r; // Widerstandswert in Ohm private double u; // Aktuell angelegte Spannung in Volt /** * Initialisiert Bauteil mit seinem Widerstand. * @param ohm Widerstand in Ohm */ public Spule(double ohm) { this.r = ohm; } /** * Liefert den Widerstand des Bauteils. * @return Widerstand des Bauteils */ public double getR() { return r; } /** * Modelliert das Anlegen einer Spannung. * @param u die angelegte Spannung */ public void setU(double u) { this.u = u; } /** * Modelliert den aktuellen Stromfluss. * @return Stromfluss bei aktuell angelegter Spannung */ public double getI() { return u/r; } } Als Eigenschaft aller Dinge mit einem Widerstand definieren wir: /** * Modelliert die Eigenschaft einen ohmschen Widerstand zu besitzen. */ public interface Widerstand { /** * Liefert den ohmschen Widerstand. * @return Widerstand */ double getR(); } 6 Um auszudrücken, dass eine Spule ein Ding mit einem Widerstand ist, muss die Definition der Spule geändert werden: package oop.blatt_11.aufgabe_4; /** * Instanzen dieser Klasse modellieren Spulen mit Ohmschem Widerstand. */ public class Spule implements Widerstand { private double r; // Widerstandswert in Ohm private double u; // Aktuell angelegte Spannung in Volt /** * Initialisiert Bauteil mit seinem Widerstand. * @param ohm Widerstand in Ohm */ public Spule(double ohm) { this.r = ohm; } /** * Modelliert das Anlegen einer Spannung. * @param u die angelegte Spannung */ public void setU(double u) { this.u = u; } /* (non-Javadoc) * @see oop.blatt_11.aufgabe_4.Widerstand#getR() */ @Override public double getR() { return r; } /** * Modelliert den aktuellen Stromfluss. * @return Stromfluss bei aktuell angelegter Spannung */ public double getI() { return u/r; } } Jetzt können wir sagen, dass Reihen– und Parallelschaltungen aus Dingen mit einem Widerstand zusammengesetzt werden können und selbst einen Widerstand haben: package oop.blatt_11.aufgabe_4; /** * Instanzen dieser Klasse modellieren Reihenschaltungen ohmscher Widerstaende. * */ public class Reihenschaltung implements Widerstand { private Widerstand w1; private Widerstand w2; private double u; 7 /** * Initilaisiert Reihenschaltung aus zwei Widerstaenden. * @param w1 * @param w2 */ public Reihenschaltung(Widerstand w1, Widerstand w2) { this.w1 = w1; this.w2 = w2; } /* (non-Javadoc) * @see oop.blatt_11.aufgabe_4.Widerstand#getR() */ @Override public double getR() { return w1.getR()+w2.getR(); } /** * Modelliert das Anlegen einer Spannung. * @param u die angelegte Spannung */ public void setU(double u) { this.u = u; } /** * Modelliert den aktuellen Stromfluss. * @return Stromfluss bei aktuell angelegter Spannung. */ public double getI() { return this.u / getR(); } } Entsprechend kann die Klasse Parallelschaltung angepasst werden. Tun Sie dies. Damit können jetzt beliebig komplexe Schaltungen definiert werden: public class Main { public static void Widerstand Widerstand Widerstand Widerstand main(String[] args) { r1 = new Spule(50); r2 = new Spule(100); r3 = new Spule(150); r4 = new Spule(300); Reihenschaltung sr1 = new Reihenschaltung(r1, r2); Reihenschaltung sr2 = new Reihenschaltung(r3, r4); Parallelschaltung sp = new Parallelschaltung(sr1, sr2); System.out.println(sp.getR()); sp.setU(50.0); System.out.println(sp.getI()); } } 8 Dieses Beispiel sollte die Ausgabe 112.5 und 0.4444444444444444 erzeugen. Aufgabe 5 Zeichen Sie ein UML–Klassendiagramm das die Klassen von Aufgabe 5 und ihre Beziehungen darstellt. Aufgabe 6 In einer Reihenschaltung und in einer Parallelschaltung können natürlich mehr als zwei Unterschaltkreise verschaltet werden. Erweitern / Modifizieren Sie Ihre Definitionen derart, dass der Konstruktor der Reihen– und der Parallelschaltung beliebig viele Argumente akzeptiert. Die Reihenschaltung kann beispielsweise so definiert werden: package oop.blatt_11.aufgabe_6; import java.util.Arrays; import java.util.List; /** * Instanzen dieser Klasse modellieren Reihenschaltungen ohmscher Widerstaende. * */ public class Reihenschaltung implements Widerstand { private List<Widerstand> komponenten; private double u; /** * Initilaisiert Reihenschaltung aus zwei Widerstaenden. * @param w Wiederstaende */ public Reihenschaltung(Widerstand... w) { this.komponenten = Arrays.asList(w); } /* (non-Javadoc) * @see oop.blatt_11.aufgabe_4.Widerstand#getR() */ @Override public double getR() { double r = 0.0; for (Widerstand w: komponenten) { r = r + w.getR(); } return r; } /** * Modelliert das Anlegen einer Spannung. * @param u die angelegte Spannung */ public void setU(double u) { this.u = u; } /** * Modelliert den aktuellen Stromfluss. * @return Stromfluss bei aktuell angelegter Spannung. */ public double getI() { return this.u / getR(); 9 } } 1. Modifizieren Sie die Definition der Parallelschaltung entsprechend. 2. Zeichen Sie ein Klassendiagramm Ihrer so veränderten Definitionen. 3. Berechnen Sie mit Hilfe Ihrer Klassen den Strom der durch folgendes Netz1 fließt, wenn die Spannungsquelle 20V liefert. Aufgabe 7 Die Klassen Reihenschaltung und in einer Parallelschaltung haben eine Gemeinsamkeit: Es handelt sich bei beiden um eine Kollektion von Komponenten. Gemeinsames wird zweimal definiert, dies nennt man Redundanz oder einfach Wiederholung des Gleichen. 1. Warum ist Redundanz / Wiederholung in der Software–Entwicklung möglichst zu vermeiden? 2. Mit welchem Mittel lassen sich Redundanz / Wiederholung bei Klassendefinitionen vermeiden? 3. Definieren Sie zur Vermeidung der Redundanz eine abstrakte Klasse KomplexeSchaltung als Basisklasse von Reihenschaltung und Parallelschaltung und passen Sie diese an. 4. Zeichen Sie ein Klassendiagramm Ihrer so veränderten Definitionen. Aufgabe 8 – Hausaufgabe 9 (klein) Bei den Schaltnetzen, die mit den Definitionen von oben modelliert werden können, handelt es sich um Zweipol– Schaltungen. Also um Schaltnetze mit zwei “Anschlussklemmen” über die eine Spannung angelegt werden kann. Die Spannungen und Ströme in einem solchen Schaltnetz und all seinen Teilnetzen können mit Hilfe der Kirchhoff’schen Regeln2 bestimmt werden werden. Wir können damit also nicht nur den Strom bei einer angelegten Spannung für die Gesamtschaltung berechnen, sondern auch für alle Teilschaltungen. Dabei geht man nach folgendem Algorithmus vor3 : 1. Berechne den Gesamtwiderstand R des Schaltkreises. 2. Berechne aus R und der angelegten Spannung U den Strom I = U/R der durch den gesamten Schaltkreis fließt. 3. Handelt es sich sich bei dem Stromkreis um eine Spule, dann ist die Aufgabe erledigt. 1 Bild aus http://homepages.thm.de/ hg6458/nga-Dateien/aufgbl4.pdf Veranstaltung NTG 3 Kirchhoffsche Knoten- und Maschenregeln als rekursiver Algorithmus 2 Siehe 10 4. Handelt es sich um eine Parallelschaltung, dann verteile Spannung U und Strom I nach folgender Regel auf die Teilschaltungen t: • Die Spannung Ut ist in jedem Teilschaltkreis t gleich der Gesamtspannung Ut = U . • Der Strom It in jedem Teilschaltkreis t entspricht seinem Anteil am Gesamtwiderstand. It = U/Rt 5. Handelt es sich um eine Reihenschaltung, dann verteile Spannung U und Strom I nach folgender Regel auf die Teilschaltungen t: • Der Strom It ist in jedem Teilschaltkreis tgleich dem Gesamtstrom It = I. • Die Spannung Ut in jedem Teilschaltkreis t entspricht seinem Anteil am Gesamtwiderstand. Ut = I ∗ Rt Dieser Algorithmus wird für Schaltnetze und rekursiv für ihre Teilnetze ausgeführt und führt dazu, dass wir für das Schaltnetze und all seine Teilnetze und Komponenten Widerstand, Spannung und Stromfluss “ablesen” können. Damit dieses Ablesen funktioniert, müssen Schaltkreise und ihre Komponenten so modifiziert werden, dass nicht nur der Widerstand R, sondern auch die Spannung U und der Strom I abgefragt werden können. Wir haben es so mit zwei Schnittstellen zu tun: • Die “äußere” Schnittstelle zu einem externen Beobachter, der Spannung und Strom in einem (Teil–) Schaltkreis ablesen will. • Die “innere” Schnittstelle die dazu dient die verschiedenen Arten von Schaltkreisen unter ein einem einheitlichen Typ zusammenzufassen. Die erste Schnittstelle ist neu, die zweite wurde oben als Interface Widerstand realisiert. Die äußere – die “Beobachter-” – Schnittstelle implementieren wir als Interface Zweipol: package oop.blatt_11.aufgabe_8; /** * Modelliert die von aussen sichtbaren / messbaren Eigenschaften eines Zweipols. * */ public interface Zweipol { /** * Liefert den aktuellen Stromfluss. * @return Stromfluss */ double getI(); /** * Liefert die aktuelle Spannung. * @return Spannung */ double getU(); } Die inneren Schnittstelle – die zur Vereinheitlichung der unterschiedlichen Netztypen – implementieren wir als abstrakte Klasse und nennen sie jetzt Schaltkreis (statt wie oben Widerstand). Jeder Schaltkreis kann von außen vermessen werden und implementiert darum das Interface Zweipol. Die Klasse ist die Basis aller Arten Schaltkreisen und fasst deren Fähigkeit zur Berechnung des Widerstands und und der Anwendung der Kirchhoffschen Regeln zusammen. package oop.blatt_11.aufgabe_8; /** * Instzanzen abgeleiteter Klassen modellieren Zweipol- (Unter-) Schaltkreise. 11 * */ abstract class Schaltkreis implements Zweipol { /* (non-Javadoc) * @see oop.blatt_11.aufgabe_8.Zweipol#getI() */ @Override public abstract double getI(); /* (non-Javadoc) * @see oop.blatt_11.aufgabe_8.Zweipol#getU() */ @Override public abstract double getU(); /** * Liefert den Widerstand des Teilschaltkreises. * @return Widerstand */ protected abstract double getR(); /** * Wendet die Kirchhoffschen Regeln an zur Berechnung der * der Spannungen und Stroeme in den Unterschaltkreisen dieses Schaltkreises. * @param u vorgegebene Gesamtspannung * @param i vorgebener Gesamtstrom */ protected abstract void kirchhoff(double u, double i); } Bringt man Spannungsquelle und einen Schaltkreis zusammen, dann kann man Spannungen und Ströme an allen Komponenten und Teilschaltkreisen des Schaltkreises beobachten. Eine Spannungsquelle ist schnell definiert: package oop.blatt_11.aufgabe_8; /** * Instanzen dieser Klasse modellieren (Gleichstrom-) Spannungquellen. * */ public class Spannungsquelle { private double u; /** * Erzeugt eine Spannungsquelle mit gegebener Spannung. * @param u die Spannung. */ public Spannungsquelle(double u) { this.u = u; } /** * Liefert die Spannung der Spannungsquelle. * @return Spannung */ public double getU() { return u; 12 } } Wird eine Spannungsquelle und ein Schaltkreis zusammengebracht, dann fließt Strom und Spannungen liegen an. Dazu muss der Gesamt-Widerstand des Schaltkreises berechnet und dann die Kirchhoffschen Gesetze angewendet werden: package oop.blatt_11.aufgabe_8; /** * Diese statische Klasse enthaelt Funktionen die auf Schaltkreisen operieren. */ public final class Schaltkreise { private Schaltkreise() {} /** * Verbindet eine Spannungsquelle mit einem Schaltkreis. * <p> * Das Verbinden stoesst die Berechnung der Spannungen und * Stroeme im Schaltkreis und seinen Komponenten und * und Teilkreisen an. * <p> * @param q Spannungsquelle * @param s Schaltkreis */ public static void kopple(Spannungsquelle q, Schaltkreis s) { double r = s.getR(); double u = q.getU(); double i = u/r; s.kirchhoff(u, i); } } Die Anwendung der Kirchhoffschen Regeln ist ein rekursiver Algorithmus, der in den Spulen als elementaren Komponenten endet: package oop.blatt_11.aufgabe_8; /** * Instanzen dieser Klasse modellieren Spulen mit Ohmschem Widerstand. */ public class Spule extends Schaltkreis { private double r; // Widerstandswert in Ohm private double u; // Aktuell angelegte Spannung in Volt private double i; // Aktuell fliessender Strom in Ampere /** * Initialisiert Bauteil mit seinem Widerstand. * @param ohm Widerstand in Ohm */ public Spule(double ohm) { this.r = ohm; } @Override public double getI() { return i; } @Override 13 public double getU() { return u; } @Override protected double getR() { return r; } @Override protected void kirchhoff(double u, double i) { this.i = i; this.u = u; } } Bei komplexen Schaltnetzen muss der Algorithmus von oben auf rekursiv die Komponenten angewendet werden. Z.B. für eine Reihenschaltung: package oop.blatt_11.aufgabe_8; /** * Instanzen dieser Klasse modellieren Reihenschaltungen von Schaltkreisen. * */ public class Reihenschaltung extends KomplexeSchaltung { private double i; private double u; /** * Initilaisiert Reihenschaltung aus zwei Widerstaenden. * @param s Teilschaltkreise */ public Reihenschaltung(Schaltkreis... s) { super(s); } @Override public double getI() { return this.i; } @Override public double getU() { return this.u; } @Override protected double getR() { return 0.0; // TODO richtigen Wert zurueck geben } @Override protected void kirchhoff(double u, double i) { this.i = i; this.u = u; for (Schaltkreis s: komponenten) { s.kirchhoff(0.0, 0.0); // TODO richtige Parameter einsetzen } } 14 } Ein Test mit einer einfachen Schaltung ist: package oop.blatt_11.aufgabe_8; import static org.junit.Assert.*; import org.junit.Test; public class SchaltkreiseTest { @Test public void test() { Schaltkreis r1 = new Spule(10); Schaltkreis r2 = new Spule(30); Schaltkreis r3 = new Spule(20); Schaltkreis Schaltkreis ps = new Parallelschaltung(r2, r3); rs = new Reihenschaltung(r1, ps); Spannungsquelle quelle = new Spannungsquelle(220); Schaltkreise.kopple(quelle, rs); assertEquals(10.0, assertEquals(30.0, assertEquals(20.0, assertEquals(12.0, assertEquals(22.0, r1.getR(), r2.getR(), r3.getR(), ps.getR(), rs.getR(), 0.0001); 0.0001); 0.0001); 0.0001); 0.0001); assertEquals(100.0, r1.getU(), 0.0001); assertEquals(10.0, r1.getI(), 0.0001); assertEquals(120.0, r2.getU(), 0.0001); assertEquals(4.0, r2.getI(), 0.0001); assertEquals(120.0, r3.getU(), 0.0001); assertEquals(6.0, r3.getI(), 0.0001); assertEquals(120.0, ps.getU(), 0.0001); assertEquals(10.0, ps.getI(), 0.0001); assertEquals(220.0, rs.getU(), 0.0001); assertEquals(10.0, rs.getI(), 0.0001); } } Ergänzen Sie die Definitionen derart, dass dieser Testfall und eventuell weitere selbst definierte Testfälle bestanden werden. Ausgabe: 6.1.2014 Abgabe: 4.2.2014 Lernziele: Klassenentwurf, Datenmodellierung mit Klassen, Interfaces und abstrakten Klassen. Rekursive Algorithmen auf strukturierten Daten. Bewertungskriterien: 15 0 Punkte 8 Punkte 10 Punkte keine Abgabe oder Abgabe mit formalen Mängeln (kein Quellcode oder nicht ausführbar). für eine Lösung bei der der vorgegebene Testfall bestanden wird. für eine korrekte Lösung (wird eventuell mit weiteren Testfällen geprüft).