anwenden:ganzzahl
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
— | anwenden:ganzzahl [2020-07-26 17:05] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1 | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== Ganzzahl : ein Datentyp für beinahe beliebig große Ganzzahlen ====== | ||
+ | > Gott schuf die ganzen Zahlen. Der Rest ist Menschenwerk. | ||
+ | >> | ||
+ | |||
+ | Die Grunddatentypen haben einen beschränkten Wertebereich. | ||
+ | Dieser ist für manche Anwendung zu klein. | ||
+ | Verschlüsselungsalgorithmen z.B. arbeiten heute mit 512 Bit, | ||
+ | d.h. also etwa 150 Dezimalstellen. | ||
+ | Dafür wird ein Ganzzahltyp benötigt, | ||
+ | der Werte mit beliebig vielen Stellen erlaubt, | ||
+ | zumindest soweit der Hauptspeicher des Rechners reicht. | ||
+ | |||
+ | Eine Vielzahl von Bibliotheken (z.B. | ||
+ | GMP = GNU Multiprecision library, BigNum, MPInt, Mint, bigInt, LiDIA, bnlib, CLN) | ||
+ | widmet sich der Fragestellung großer Ganzzahlen für | ||
+ | bestimmte Compiler und Plattformen. | ||
+ | Unter der Bezeichnung | ||
+ | [[http:// | ||
+ | gibt es einen Standardisierungsvorschlag auf der Basis von Boost.Integer. | ||
+ | |||
+ | ===== Anforderungen ===== | ||
+ | Was muss ein solcher Ganzzahltyp beherrschen? | ||
+ | Natürlich Rechnen ('' | ||
+ | Erhöhen und Vermindern, Vergleiche. | ||
+ | Die Ein- und Ausgabe erfolgt über Datenströme der '' | ||
+ | Die Umwandlung von und zu Zeichenketten | ||
+ | ('' | ||
+ | Bitweise Operationen werden nicht unterstützt. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Klassenschnittstelle ===== | ||
+ | <code cpp> | ||
+ | //: ganzzahl.h : Ganzzahlen beliebiger Genauigkeit - R.Richter 2004-09-24 | ||
+ | ///////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | #ifndef GANZZAHL_H | ||
+ | #define GANZZAHL_H | ||
+ | |||
+ | // Abhängigkeiten | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | class Ganzzahl | ||
+ | { | ||
+ | public: | ||
+ | </ | ||
+ | Ganzzahlen können ohne Vorgabe (0), aus einem '' | ||
+ | oder aus einer Zeichenkette wie ''" | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | // Konstruktoren | ||
+ | Ganzzahl(); | ||
+ | Ganzzahl(long n); | ||
+ | Ganzzahl(std:: | ||
+ | </ | ||
+ | Die Rückwandlung in eine Zeichenkette ist jederzeit möglich, | ||
+ | die Umwandlung in '' | ||
+ | wenn die Grenzen des Zieldatentyps eingehalten werden. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | // Konversion | ||
+ | std::string to_string() const; | ||
+ | long to_long() const; | ||
+ | </ | ||
+ | Andernfalls wird eine '' | ||
+ | Die andere Fehlerart tritt beim Dividieren auf. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | // Fehlerklassen | ||
+ | class Bereichsfehler {}; | ||
+ | class Nulldivision {}; | ||
+ | </ | ||
+ | Die gewöhnlichen Rechenoperationen werden weiter unten | ||
+ | über die C-typischen Verbundoperatoren definiert. | ||
+ | |||
+ | <code cpp> | ||
+ | // Operatoren | ||
+ | Ganzzahl& | ||
+ | Ganzzahl& | ||
+ | Ganzzahl& | ||
+ | Ganzzahl& | ||
+ | Ganzzahl& | ||
+ | </ | ||
+ | Inkrement und Dekrement existieren als voran- und nachgestellte | ||
+ | Operanden mit unterschiedlicher Bedeutung. | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | Ganzzahl& | ||
+ | Ganzzahl& | ||
+ | Ganzzahl | ||
+ | Ganzzahl | ||
+ | </ | ||
+ | Das Vorzeichen '' | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | Ganzzahl operator-() const; | ||
+ | </ | ||
+ | Häufig wird in C auf "Null sein" geprüft: | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | bool operator!() const; | ||
+ | </ | ||
+ | Da die Implementierung mit Zeigern '' | ||
+ | auf dynamisch bereitgestellten Speicher zugreifen wird, | ||
+ | sind Kopierkonstruktor, | ||
+ | Die Entscheidung für '' | ||
+ | Alternativ wäre hier ein privater '' | ||
+ | Dann wäre manches einfacher, | ||
+ | auch die drei nachstehenden Funktionen bräuchten nicht geschrieben werden. | ||
+ | |||
+ | <code cpp> | ||
+ | // Kopie, Zuweisung, Destruktor | ||
+ | Ganzzahl(Ganzzahl const& n); | ||
+ | Ganzzahl& | ||
+ | | ||
+ | private: | ||
+ | char* p; // dynamisch allokiert | ||
+ | </ | ||
+ | Einzelnen Rechenoperationen wird der Zugriff auf die interne | ||
+ | Datenrepräsentation gestattet, z.B. einem Vergleichsoperator. | ||
+ | |||
+ | <code cpp> | ||
+ | // Freunde | ||
+ | friend bool operator< | ||
+ | }; | ||
+ | </ | ||
+ | Damit ist die Klasse vollständig definiert. | ||
+ | Als globale Funktionen angemeldet werden der Satz der Vergleichsoperatoren | ||
+ | |||
+ | <code cpp> | ||
+ | // Vergleich | ||
+ | bool operator< | ||
+ | bool operator> | ||
+ | bool operator< | ||
+ | bool operator> | ||
+ | bool operator==(Ganzzahl const& m, Ganzzahl const& n); | ||
+ | bool operator!=(Ganzzahl const& m, Ganzzahl const& n); | ||
+ | </ | ||
+ | und die zweistelligen Rechenoperationen | ||
+ | |||
+ | <code cpp> | ||
+ | // symmetrische arithmetische Funktionen | ||
+ | Ganzzahl operator+(Ganzzahl const& m, Ganzzahl const& n); | ||
+ | Ganzzahl operator-(Ganzzahl const& m, Ganzzahl const& n); | ||
+ | Ganzzahl operator*(Ganzzahl const& m, Ganzzahl const& n); | ||
+ | Ganzzahl operator/ | ||
+ | Ganzzahl operator%(Ganzzahl const& m, Ganzzahl const& n); | ||
+ | </ | ||
+ | sowie Ein- und Ausgabeoperatoren. | ||
+ | |||
+ | <code cpp> | ||
+ | // I/O | ||
+ | std:: | ||
+ | std:: | ||
+ | </ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== inline-Methoden ===== | ||
+ | Für fast alle globalen Operationen sind inline-Implementierungen möglich, | ||
+ | bei denen der Überbau eines zusätzlichen Funktionsaufrufs vermieden | ||
+ | und die entsprechenden Anweisungen direkt eingebaut werden. | ||
+ | Dazu werden dem Compiler diese Funktionsrümpfe offengelegt. | ||
+ | Alle Vergleiche lassen sich auf die Kleiner-Als-Operation | ||
+ | zurückführen. Dies ist eine kleine Übung in mathematischer Logik: | ||
+ | |||
+ | <code cpp> | ||
+ | inline bool operator> | ||
+ | { | ||
+ | return n < m; | ||
+ | } | ||
+ | |||
+ | inline bool operator> | ||
+ | { | ||
+ | return !(m < n); | ||
+ | } | ||
+ | |||
+ | inline bool operator< | ||
+ | { | ||
+ | return !(n < m); | ||
+ | } | ||
+ | |||
+ | inline bool operator==(Ganzzahl const& m, Ganzzahl const& n) | ||
+ | { | ||
+ | return !(m < n || n < m); | ||
+ | } | ||
+ | |||
+ | inline bool operator!=(Ganzzahl const& m, Ganzzahl const& n) | ||
+ | { | ||
+ | return m < n || n < m; | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | Die Ausgabe erfolgt über den Umweg einer Zeichenkette. | ||
+ | |||
+ | <code cpp> | ||
+ | inline std:: | ||
+ | { | ||
+ | return os << n.to_string(); | ||
+ | } | ||
+ | </ | ||
+ | Die zweistelligen Rechenoperationen werden | ||
+ | auf die zugeordneten Verbundoperatoren zurückgeführt. | ||
+ | Für '' | ||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | // Ganzzahl summe = m; // Kopie des linken Operanden | ||
+ | // summe += n; | ||
+ | // return summe; | ||
+ | </ | ||
+ | ausgeführt, | ||
+ | |||
+ | <code cpp> | ||
+ | inline Ganzzahl operator+(Ganzzahl const& m, Ganzzahl const& n) | ||
+ | { | ||
+ | return Ganzzahl(m) += n; | ||
+ | } | ||
+ | |||
+ | inline Ganzzahl operator-(Ganzzahl const& m, Ganzzahl const& n) | ||
+ | { | ||
+ | return Ganzzahl(m) -= n; | ||
+ | } | ||
+ | |||
+ | inline Ganzzahl operator*(Ganzzahl const& m, Ganzzahl const& n) | ||
+ | { | ||
+ | return Ganzzahl(m) *= n; | ||
+ | } | ||
+ | |||
+ | inline Ganzzahl operator/ | ||
+ | { | ||
+ | return Ganzzahl(m) /= n; | ||
+ | } | ||
+ | |||
+ | inline Ganzzahl operator%(Ganzzahl const& m, Ganzzahl const& n) | ||
+ | { | ||
+ | return Ganzzahl(m) %= n; | ||
+ | } | ||
+ | </ | ||
+ | Die nachgestellten Operatoren '' | ||
+ | der nach der Wertänderung für weitere Rechenoperationen benutzt wird. | ||
+ | |||
+ | <code cpp> | ||
+ | inline Ganzzahl Ganzzahl:: | ||
+ | { | ||
+ | Ganzzahl alt(*this); | ||
+ | ++ *this; | ||
+ | return alt; | ||
+ | } | ||
+ | |||
+ | inline Ganzzahl Ganzzahl:: | ||
+ | { | ||
+ | Ganzzahl alt(*this); | ||
+ | -- *this; | ||
+ | return alt; | ||
+ | } | ||
+ | |||
+ | #endif // GANZZAHL_H | ||
+ | </ | ||
+ | Die Klassenschnittstelle und eine Reihe globaler Funktionen sind damit festgelegt. | ||
+ | Was noch fehlt, ist | ||
+ | [[anwenden: | ||
+ | |||