• Martin Thoma
  • Home
  • Categories
  • Tags
  • Archives
  • Support me

Fractions in C++

Contents

  • Fractions in C++
    • First some math
      • Names
      • Operations
      • Euklids algorithm
    • C++ Code
    • See also

Today, I thought I should try to implement a class in C++ that deals with fractions. This is actually quite easy as I'll show you.

First some math

Names

When you have a fraction \(\frac{a}{b}\) then \(a\) is called numerator and \(b\) is called denominator.

Operations

The rules for basic operations are simple:

Addition: \(\frac{a}{b} + \frac{c}{d} = \frac{a \cdot d + c \cdot b}{b \cdot d}\)

Subtraction: \(\frac{a}{b} - \frac{c}{d} = \frac{a \cdot d - c \cdot b}{b \cdot d}\)

Multiplication: \(\frac{a}{b} \cdot \frac{c}{d} = \frac{a \cdot c}{b \cdot d}\)

Division: \(\frac{a}{b} : \frac{c}{d} = \frac{a \cdot d}{b \cdot c}\)

Euklids algorithm

You can calculate the greatest common divisor with Euklids algorithm. If you don't know it, please read the Wikipedia article.

Knowing the greatest common divisor is important, because we want that our Faction class automatically cancels those factors so that the numerator and denominator are as small as possible.

C++ Code

#include <iostream>

using namespace std;

class Fraction {
    private:
        // Calculates the greates common divisor with
        // Euclid's algorithm
        // both arguments have to be positive
        long long gcd(long long a, long long b) {
            while (a != b) {
                if (a > b) {
                    a -= b;
                } else {
                    b -= a;
                }
            }
            return a;
        }

    public:
        long long numerator, denominator;

        Fraction() {
            numerator = 0;
            denominator = 1;
        }

        Fraction(long long n, long long d) {
            if (d==0) {
                cerr << "Denominator may not be 0." << endl;
                exit(0);
            } else if (n == 0) {
                numerator = 0;
                denominator = 1;
            } else {
                int sign = 1;
                if (n < 0) {
                    sign *= -1;
                    n *= -1;
                }
                if (d < 0) {
                    sign *= -1;
                    d *= -1;
                }

                long long tmp = gcd(n, d);
                numerator = n/tmp*sign;
                denominator = d/tmp;
            }
        }

        operator int() {return (numerator)/denominator;}
        operator float() {return ((float)numerator)/denominator;}
        operator double() {return ((double)numerator)/denominator;}
};

Fraction operator+(const Fraction& lhs, const Fraction& rhs) {
    Fraction tmp(lhs.numerator*rhs.denominator
                +rhs.numerator*lhs.denominator,
                lhs.denominator*rhs.denominator);
    return tmp;
}

Fraction operator+=(Fraction& lhs, const Fraction& rhs) {
    Fraction tmp(lhs.numerator*rhs.denominator
                +rhs.numerator*lhs.denominator,
                lhs.denominator*rhs.denominator);
    lhs = tmp;
    return lhs;
}

Fraction operator-(const Fraction& lhs, const Fraction& rhs) {
    Fraction tmp(lhs.numerator*rhs.denominator
                -rhs.numerator*lhs.denominator,
                lhs.denominator*rhs.denominator);
    return tmp;
}

Fraction operator-=(Fraction& lhs, const Fraction& rhs) {
    Fraction tmp(lhs.numerator*rhs.denominator
                -rhs.numerator*lhs.denominator,
                lhs.denominator*rhs.denominator);
    lhs = tmp;
    return lhs;
}

Fraction operator*(const Fraction& lhs, const Fraction& rhs) {
    Fraction tmp(lhs.numerator*rhs.numerator,
               lhs.denominator*rhs.denominator);
    return tmp;
}

Fraction operator*=(Fraction& lhs, const Fraction& rhs) {
    Fraction tmp(lhs.numerator*rhs.numerator,
               lhs.denominator*rhs.denominator);
    lhs = tmp;
    return lhs;
}

Fraction operator*(int lhs, const Fraction& rhs) {
    Fraction tmp(lhs*rhs.numerator,rhs.denominator);
    return tmp;
}

Fraction operator*(const Fraction& rhs, int lhs) {
    Fraction tmp(lhs*rhs.numerator,rhs.denominator);
    return tmp;
}

Fraction operator/(const Fraction& lhs, const Fraction& rhs) {
    Fraction tmp(lhs.numerator*rhs.denominator,
                 lhs.denominator*rhs.numerator);
    return tmp;
}

std::ostream& operator<<(std::ostream &strm, const Fraction &a) {
    if (a.denominator == 1) {
        strm << a.numerator;
    } else {
        strm << a.numerator << "/" << a.denominator;
    }
    return strm;
}

int main() {
    Fraction a(1,3);
    Fraction b(3,28);
    Fraction c;

    c = a + b;
    cout << c << "\t(should be 37/84)" << endl;

    c = a - b;
    cout << c << "\t(should be 19/84)" << endl;

    c = a * b;
    cout << c << "\t(should be 1/28)" << endl;

    c = a / b;
    cout << c << "\t(should be 28/9)" << endl;

    c = -1 * b;
    cout << c << "\t(should be -3/28)" << endl;

    c = b * (-1);
    cout << c << "\t(should be -3/28)" << endl;

    c = Fraction(-100,3);
    cout <<    (int)c << "\t(should be -33)" << endl;
    cout <<  (float)c << "\t(should be -33.3...)" << endl;
    cout << (double)c << "\t(should be -33.3...)" << endl;

    a -= b;
    cout << a << "\t(should be 19/84)" << endl;

    return 0;
}

See also

You might also be interested in my article about operator overloading.

Does anybody know if there is an "official" Fraction class?


Published

Jun 1, 2013
by Martin Thoma

Category

Code

Tags

  • CPP 10

Contact

  • Martin Thoma - A blog about Code, the Web and Cyberculture
  • E-mail subscription
  • RSS-Feed
  • Privacy/Datenschutzerklärung
  • Impressum
  • Powered by Pelican. Theme: Elegant by Talha Mansoor