Department of Computer Science | Institute of Theoretical Computer Science | CADMO

Theory of Combinatorial Algorithms

Prof. Emo Welzl and Prof. Bernd Gärtner

// Programm: rational.h // Brueche ganzer Zahlen. #include namespace ifm { // Klasse zur Repraesentation von Bruechen ganzer Zahlen. class Rational { public: typedef int NT; Rational(const NT& n, const NT& d); // PRE: d != 0. // POST: Bruch initialisiert als n / d. Rational(const NT& n); // POST: Bruch initialisiert als n / 1. const NT& n() const; // POST: Rueckgabewert ist Zaehler des Bruchs. const NT& d() const; // POST: Rueckgabewert ist Nenner des Bruchs. Rational& operator+=(const Rational& x); // POST: x wurde zu *this addiert. Rational& operator-=(const Rational& x); // POST: x wurde von *this subtrahiert. Rational& operator*=(const Rational& x); // POST: *this wurde mit x multipliziert. Rational& operator/=(const Rational& x); // PRE: x.n() != 0 // POST: *this wurde durch x dividiert. private: void normalize(); // POST: Der Wert des Bruchs bleibt unveraendert, aber Zaehler und // Nenner sind teilerfremd, sowie der Nenner ist positiv. NT n_; // numerator (Zaehler) NT d_; // denominator (Nenner) // Invariante: d_ > 0 und (n_,d_) ist normalisiert. }; std::ostream& operator<<(std::ostream& o, const Rational& x); // POST: x wurde auf o ausgegeben; Rueckgabewert ist o. // Vergleichsoperationen: // POST: Rueckgabewert true <=> x ? y bool operator==(const Rational& x, const Rational& y); bool operator!=(const Rational& x, const Rational& y); bool operator<(const Rational& x, const Rational& y); bool operator<=(const Rational& x, const Rational& y); bool operator>(const Rational& x, const Rational& y); bool operator>=(const Rational& x, const Rational& y); unsigned int gcd(unsigned int a, unsigned int b) // POST: Rueckgabe ist der groesste gemeinsame // Teiler von a und b, wobei ggt(x,0):=ggt(0,x):=x. { if (b == 0) return a; return gcd(b, a % b); } // gcd(a, b) // // Implementation der Klasse Rational // Rational::Rational(const NT& n, const NT& d) : n_(n), d_(d) { normalize(); } Rational::Rational(const NT& n) : n_(n), d_(1) {} const Rational::NT& Rational::n() const { return n_; } const Rational::NT& Rational::d() const { return d_; } void Rational::normalize() { NT na = n_; if (n_ < 0) na = -na; NT g = ifm::gcd(na, d_); n_ /= g; d_ /= g; if (d_ < 0) { d_ = -d_; n_ = -n_; } } Rational& Rational::operator+=(const Rational& x) { n_ = n_ * x.d_ + x.n_ * d_; d_ *= x.d_; normalize(); return *this; } Rational& Rational::operator-=(const Rational& x) { n_ = n_ * x.d_ - x.n_ * d_; d_ *= x.d_; normalize(); return *this; } Rational& Rational::operator*=(const Rational& x) { n_ *= x.n_; d_ *= x.d_; normalize(); return *this; } Rational& Rational::operator/=(const Rational& x) { assert(x.n() != 0); n_ *= x.d_; d_ *= x.n_; normalize(); return *this; } Rational operator+(const Rational& x, const Rational& y) // POST: Rueckgabewert ist x + y. { Rational z = x; z += y; return z; } Rational operator-(const Rational& x, const Rational& y) // POST: Rueckgabewert ist x - y. { Rational z = x; z -= y; return z; } Rational operator*(const Rational& x, const Rational& y) // POST: Rueckgabewert ist x * y. { Rational z = x; z *= y; return z; } Rational operator/(const Rational& x, const Rational& y) // POST: Rueckgabewert ist x / y. { Rational z = x; z /= y; return z; } // // Globale Funktionen // bool operator==(const Rational& x, const Rational& y) { return x.n() * y.d() == x.d() * y.n(); } bool operator!=(const Rational& x, const Rational& y) { return !(x == y); } bool operator<(const Rational& x, const Rational& y) { return x.n() * y.d() < x.d() * y.n(); } bool operator<=(const Rational& x, const Rational& y) { return !(y < x); } bool operator>(const Rational& x, const Rational& y) { return y < x; } bool operator>=(const Rational& x, const Rational& y) { return !(x < y); } std::ostream& operator<<(std::ostream& o, const Rational& x) { return o << x.n() << "/" << x.d(); } } // namespace ifm