000
22.12.2003, 13:48 Uhr
(un)wissender
Niveauwart
|
Hallo!
Ich habe mal eine Klasse Bruch erstellt, weil mit die ungenauen doubles nicht passen und um allgemein C++ zu üben. Jetzt seid ihr gefragt: Laßt alles raus was euch einfällt, macht mich richtig nieder. (Performance, Bugs, Designfehler, Verbesserungen, ...)
Der Header
C++: |
#ifndef FRACTION_HPP_INCLUDED #define FRACTION_HPP_INCLUDED
#include <cmath> #include <exception> #include <stdexcept> #include <iostream> #include <algorithm>
class Fraction { public: Fraction(int numerator, int denominator = 1); Fraction& operator/=(const Fraction& fraction) { return (*this *= fraction.reciprocalValue()); } Fraction& operator*=(const Fraction& fraction) { m_numerator *= fraction.m_numerator; m_denominator *= fraction.m_denominator; return *this; } Fraction& operator-=(const Fraction& fraction); Fraction& operator+=(const Fraction& fraction); friend inline const Fraction operator*(const Fraction& lhf, const Fraction& rhf); friend inline const Fraction operator/(const Fraction& lhf, const Fraction& rhf); friend inline const Fraction operator+(const Fraction& lhf, const Fraction& rhf); friend inline const Fraction operator-(const Fraction& lhf, const Fraction& rhf); friend std::ostream& operator<<(std::ostream& out, const Fraction& fraction); friend std::istream& operator>>(std::istream& in, Fraction& fraction); friend inline bool operator==(const Fraction& lhf, const Fraction& rhf) { return lhf.m_numerator * rhf.m_denominator == //Brüche erweitern rhf.m_numerator * lhf.m_denominator; } friend inline bool operator!=(const Fraction& lhf, const Fraction& rhf) { return !(lhf == rhf); } friend inline bool operator<(const Fraction& lhf, const Fraction& rhf) { return lhf.m_numerator * rhf.m_denominator < //Brüche erweitern rhf.m_numerator * lhf.m_denominator; } friend inline bool operator>(const Fraction& lhf, const Fraction& rhf) { return !(lhf < rhf) && lhf != rhf; } friend inline bool operator>=(const Fraction& lhf, const Fraction& rhf) { return !(lhf < rhf); } friend inline bool operator<=(const Fraction& lhf, const Fraction& rhf) { return !(lhf > rhf); } //Den ggT (größter gemeinsamer Teiler) berechnen. //Nach dem binären Euklidische Algorithmus. int greatestCommonDivisor() const; //Denn Kehrwert berechnen. const Fraction reciprocalValue() const { return Fraction(*this).reciprocalValue(); } Fraction& reciprocalValue() { std::swap(m_numerator, m_denominator); return *this; } //Als double zurückgegebn, Präzesionsverlust möglich. double toDouble() const { return static_cast<double>(m_numerator) / static_cast<double>(m_denominator); } //Einen Bruch kürzen. Fraction& cut(); const Fraction cut() const { return Fraction(*this).cut(); } private: int m_numerator, m_denominator; //Zähler,Nenner };
#endif
|
Die Implementierung
C++: |
#include "Fraction.hpp"
Fraction::Fraction(int numerator, int denominator) { if(denominator == 0) throw std::logic_error("The denominator cannot be null!"); m_numerator = numerator; m_denominator = denominator; }
Fraction& Fraction::operator-=(const Fraction& fraction) { //Brüche erweitern int numerator = fraction.m_numerator * m_denominator; m_denominator *= fraction.m_denominator; m_numerator *= fraction.m_denominator; m_numerator -= numerator; return *this; }
Fraction& Fraction::operator+=(const Fraction& fraction) { //Brüche erweitern int numerator = fraction.m_numerator * m_denominator; m_denominator *= fraction.m_denominator; m_numerator *= fraction.m_denominator; m_numerator += numerator; return *this; }
const Fraction operator*(const Fraction& lhf, const Fraction& rhf) { return Fraction(lhf.m_numerator * rhf.m_numerator, lhf.m_denominator * rhf.m_denominator); }
const Fraction operator/(const Fraction& lhf, const Fraction& rhf) { return lhf * rhf.reciprocalValue(); }
const Fraction operator+(const Fraction& lhf, const Fraction& rhf) { return Fraction(lhf) += rhf; }
const Fraction operator-(const Fraction& lhf, const Fraction& rhf) { return Fraction(lhf) -= rhf; }
std::ostream& operator<<(std::ostream& out, const Fraction& fraction) { return out << fraction.m_numerator << "/" << fraction.m_denominator; }
std::istream& operator>>(std::istream& in, Fraction& fraction) { int numerator, denominator; in >> numerator; if(!in.fail()) in >> denominator; else { throw std::runtime_error("Sorry, wrong input, only integer are allowed!"); } if(!in.fail()) { fraction.m_numerator = numerator; if(denominator != 0) { fraction.m_denominator = denominator; } else { throw std::logic_error("The denominator cannot be null!"); } } else { throw std::runtime_error("Sorry, wrong input, only integer are allowed!"); } return in; }
int Fraction::greatestCommonDivisor() const { int numerator = m_numerator, denominator = m_denominator, divCounter = 0; while(numerator % 2 == 0 && denominator % 2 == 0) { numerator /= 2; denominator /= 2; divCounter++; } do { while(numerator % 2 == 0) numerator /= 2; if(numerator < denominator) std::swap(numerator, denominator); numerator -= denominator; } while(numerator != 0); return denominator * static_cast<int>( pow(2, divCounter) ); }
Fraction& Fraction::cut() { int gcD = greatestCommonDivisor(); if(gcD != 1) { m_numerator /= gcD; m_denominator /= gcD; } return *this; }
int main() { Fraction one(2,3); std::cout << one << "\n"; Fraction two(3,3); std::cout << two << "\n"; Fraction third = two / one; std::cout << third << "\n"; std::cout << third.cut() << "\n"; Fraction fourth = one + two; std::cout << fourth << "\n"; std::cout << fourth.cut() << "\n"; std::cout << (Fraction(8,9) == Fraction(16,18)) << "\n"; std::cout << (Fraction(8,9) < Fraction(16,18)) << "\n"; std::cout << Fraction(1,2).reciprocalValue() << "\n"; return 0; }
|
-- Wer früher stirbt ist länger tot. |