C++-Programmierung/ Brüche/ Umwandlung aus anderen Datentypen

Aus Wikibooks

Wechseln zu: Navigation, Suche


Um aus einer Variable eines andren Datentyps in einen Bruch umzuwandeln, übergibt man einem Konstruktor diese Variable und lässt ihn die Umwandlung durchführen. Sie erinnern sich bestimmt noch daran, dass im ersten Kapitel dieses Abschnittes stand, die Standardparameter des Konstruktors würden später besprochen. Dieser Zeitpunkt ist nun gekommen. Zur Erinnerung, seine Deklaration innerhalb der Klasse lautete:

Crystal Clear app terminal.png
class Bruch{
public:
    Bruch(int zaehler = 0, unsigned int nenner = 1);

// ...
};

Bruch::Bruch(int zaehler, unsigned int nenner):
    m_zaehler(zaehler),
    m_nenner(nenner){
    kuerzen();
}

Die Definition steht, wie Sie oben sehen, außerhalb der Klasse. Innerhalb der Initialisierungsliste, welche durch einen Doppelpunkt eingeleitet wird, werden die Membervariablen mit den übergebenen Parametern initialisiert. Innerhalb des Funktionsrumpfes wird die Methode kuerzen() aufgerufen, um den Buch falls nötig zu kürzen.

Beachten Sie, dass die Standardparameter nur bei der Deklaration, nicht aber bei der Definition einer Funktion angegeben werden. Unser Konstruktor übernimmt 2 int-Werte und beide besitzen einen Standardwert, daher kann er in 3 Formen aufgerufen werden:

Crystal Clear app terminal.png
Bruch bruch1()     // erzeugt (0/1)
Bruch bruch2(5)    // erzeugt (5/1)
Bruch bruch3(3, 4) // erzeugt (3/4)

Die erste Form entspricht einem Defaultkonstruktor und setzt den Wert des Buches auf (0/1), was dem ganzzahligen Wert   entspricht. In der zweiten Form wird 1 int-Wert übergeben, der resultierende Buch entspricht diesem Wert, da der Nenner dank des Standardparameters auf 1 gesetzt wird. Die dritte Form übernimmt schließlich 2 int-Werte, der erste gibt den Zähler und der zweite den Nenner des Bruches an.

Auch an dieser Stelle soll noch einmal darauf hingewiesen werden, dass der Nenner nicht negativ sein kann, daher ist dieser Parameter auch vom Typ unsigned int welcher nur positive Werte zulässt.

Symbol move vote.svg
Thema wird später näher erläutert…

Bitte beachten Sie, dass der Nenner eines Buches normalerweise nicht 0 sein kann. Normalerweise würde man dem in C++ mit einer Ausnahme begegnen. Da wir Ausnahmen aber bisher nicht besprochen haben und es auch noch eine Weile dauern wird, bis wir dieses Thema behandeln, werden wir dem Umstand, dass es möglich ist dem Konstruktor von Buch eine 0 als Nenner zu übergeben, erst einmal ignorieren. Später kommen wir auf diesen Punkt aber noch einmal zurück.

[Bearbeiten] Gleitkommazahl wird Bruch

Wir haben jetzt die Umwandlung von ganzen Zahlen in Brüche besprochen. Als nächstes wollen wir eine Gleitkommazahl in einen Bruch umwandeln. Hierfür benötigen wir einen zweiten Konstruktor, welcher eine Gleitkommazahl übernimmt und Sie in einen Bruch umwandelt:

Crystal Clear app terminal.png
class Bruch{
public:
    Bruch(int zaehler = 0, unsigned int nenner = 1);
    Bruch(double wert);

// ...
};

Bruch::Bruch(double wert):
    m_zaehler(static_cast<int>(wert*1000000.0+0.5)),
    m_nenner(1000000){
    kuerzen();
}

Es ist kaum möglich, einen double-Wert zuverlässig in einen Bruch umzuwandeln, da die Datentypen, die wir für Zäher ( int) und Nenner ( unsigned int) verwenden, den Wertebereich unserer Brüche gewaltig einschränken. Dieser Konstruktor ist daher kaum praxistauglich, aber als Beispiel sollte er genügen. Einmal vorausgesetzt, dass ein int 4 Byte groß ist, beachtet er 3 Vorkomma- und 6 Nachkommastellen.

Wir setzen den Nenner des Buches auf 1000000, dann multiplizieren wir den übergebenen Wert mit 1000000. Würde man jetzt Zähler durch Nenner teilen, hätte man wieder exakt den Wert, der übergeben wurde. Da der Zähler aber ein int- und kein double-Wert sein muss, müssen wir ihn noch umwandeln. Da eine solche Umwandlung aber alle Nachkommastellen abschneidet, anstatt kaufmännisch korrekt zu runden, addieren wir den double-Wert vorher mit 0.5, was dazu führt, das die Zahl nach den abschneiden der Nachkommastellen kaufmännisch gerundet wurde.

Alles was über 6 Nachkommastelle hinausgeht, ist also für uns nicht relevant, da es korrekt gerundet wird. Das Problem besteht darin, dass der Bruch keinen Zahler aufnehmen kann, der größer als der größtmögliche int-Wert (bei 4 Byte 2147483647) ist. Leider lässt sich dieses Problem nicht ohne weiteres lösen, daher werden wir damit leben, das dies nur ein Beispiel für die Umwandlung einer Gleitkommazahl in einen Bruch ist und keine perfekte Implementierung.

Anschließend wir im Funktionsrumpf wieder einmal die Funktion kuerzen() aufgerufen. Sie können nun also auch schreiben:

Crystal Clear app terminal.png
Bruch bruch1(0.25)       // erzeugt (1/4)
Bruch bruch2(7.0)        // erzeugt (7/1)
Bruch bruch3(999.999999) // erzeugt (999999999/1000000)

[Bearbeiten] (k)ein Kopierkonstruktor

Für unsere Bruch-Klasse werden wir keinen Kopierkonstruktor anlegen, da unser Compiler uns diese Arbeit mit einem zufriedenstellenden Ergebnis abnimmt. Oder anders ausgedrückt, Sie können ohne eine einzige Zeile Code zur Klasse hinzuzufügen schreiben:

Crystal Clear app terminal.png
Bruch bruch1(1, 5);   // erzeugt (1/5)
Bruch bruch2(bruch1); // erzeugt (1/5)


Persönliche Werkzeuge