From 69874ba9f455869494b59c08d029f8dea71df968 Mon Sep 17 00:00:00 2001 From: Tobias Berger Date: Fri, 17 Sep 2021 14:47:29 +0200 Subject: [PATCH] Operators --- fraction.cpp | 95 +++++++++++++++++++++++++++++++++- fraction.hpp | 45 +++++++++++++++-- tst_fractiontest.cpp | 118 ++++++++++++++++++++++++++++++++----------- 3 files changed, 223 insertions(+), 35 deletions(-) diff --git a/fraction.cpp b/fraction.cpp index 09f22c8..01ffc3c 100644 --- a/fraction.cpp +++ b/fraction.cpp @@ -1,5 +1,96 @@ #include "fraction.hpp" -Fraction::Fraction() -{ +namespace FractionNS { + + int gcd(int p, int q) { + while(true) { + if(p == 0) return q; + q %= p; + if(q == 0) return p; + p %= q; + } + } + + int lcm(int p, int q) { + int gcd = FractionNS::gcd(p, q); + + return gcd != 0 ? (p / gcd * q) : 0; + } + + int abs(int n) { + if(n < 0) return -n; + return n; + } + + + Fraction::Fraction(int numerator, int denominator) + { + auto gcd = FractionNS::gcd(FractionNS::abs(numerator), FractionNS::abs(denominator)); + + if(denominator < 0) { + numerator *= -1; + denominator *= -1; + } + + this->m_numerator = numerator / gcd; + this->m_denominator = denominator / gcd; + } + + int Fraction::getNumerator() const { return m_numerator; } + int Fraction::getDenominator() const { return m_denominator; } + + void Fraction::setNumerator(int numerator) { + auto gcd = std::__gcd(numerator, this->m_denominator); + this->m_numerator = numerator / gcd; + } + void Fraction::setDenominator(int denominator) { + auto gcd = std::__gcd(this->m_numerator, denominator); + this->m_denominator = denominator / gcd; + } + + QString Fraction::display() const { + return QString::number(m_numerator) + '/' + QString::number(m_denominator); + } + + bool Fraction::operator==(const int n) const { + return (double(m_numerator) / double(m_denominator)) == n; + } + bool Fraction::operator==(const float n) const { + return (double(m_numerator) / double(m_denominator)) == n; + } + bool Fraction::operator==(const double n) const { + return (double(m_numerator) / double(m_denominator)) == n; + } + bool Fraction::operator==(const Fraction& n) const { + return (this->m_numerator == n.getNumerator()) + && (this->m_denominator == n.getDenominator()); + } + + bool Fraction::operator!=(const int n) const { + return (double(m_numerator) / double(m_denominator)) != n; + } + bool Fraction::operator!=(const float n) const { + return (double(m_numerator) / double(m_denominator)) != n; + } + bool Fraction::operator!=(const double n) const { + return (double(m_numerator) / double(m_denominator)) != n; + } + bool Fraction::operator!=(const Fraction& n) const { + return (this->m_numerator != n.getNumerator()) + || (this->m_denominator != n.getDenominator()); + } + + Fraction& Fraction::operator+(const int n) const { + return Fraction(n) + *this; + } + Fraction& Fraction::operator+(const float n) const { + return Fraction(n) + *this; + } + Fraction& Fraction::operator+(const double n) const { + return Fraction(n) + *this; + } + Fraction& Fraction::operator+(const Fraction& other) const { + auto lcm = FractionNS::lcm(getDenominator(), other.getDenominator()); + return *new Fraction((getNumerator() + other.getNumerator()) * lcm, getDenominator() * lcm); + } } diff --git a/fraction.hpp b/fraction.hpp index c7e4691..fbcf81d 100644 --- a/fraction.hpp +++ b/fraction.hpp @@ -1,7 +1,44 @@ #pragma once -class Fraction -{ -public: +#include + +namespace FractionNS { + class Fraction + { + private: + int m_numerator, m_denominator; + public: Fraction(int, int); -}; + Fraction(int); + Fraction(double); + Fraction(float); + Fraction(const Fraction&); + + int getNumerator() const; + int getDenominator() const; + void setNumerator(const int); + void setDenominator(const int); + + QString display() const; + + bool operator==(const int) const; + bool operator==(const float) const; + bool operator==(const double) const; + bool operator==(const Fraction&) const; + + bool operator!=(const int) const; + bool operator!=(const float) const; + bool operator!=(const double) const; + bool operator!=(const Fraction&) const; + + Fraction& operator+(const int) const; + Fraction& operator+(const float) const; + Fraction& operator+(const double) const; + Fraction& operator+(const Fraction&) const; + + Fraction& operator+=(const int); + Fraction& operator+=(const float); + Fraction& operator+=(const double); + Fraction& operator+=(const Fraction&); + }; +} diff --git a/tst_fractiontest.cpp b/tst_fractiontest.cpp index 5c3e5fe..2c23836 100644 --- a/tst_fractiontest.cpp +++ b/tst_fractiontest.cpp @@ -2,17 +2,22 @@ #include "fraction.hpp" +using namespace FractionNS; + class FractionTest : public QObject { - Q_OBJECT + Q_OBJECT public: - FractionTest(); - ~FractionTest(); + FractionTest(); + ~FractionTest(); private slots: - void test_constructor(); - void test_equivalence(); + void test_constructor(); + void test_display(); + void test_equivalence(); + void test_addition(); + void test_inequivalence(); }; FractionTest::FractionTest() @@ -27,38 +32,93 @@ FractionTest::~FractionTest() void FractionTest::test_constructor() { - Fraction f1 = Fraction(1, 2); - QVERIFY(f1 == 0.5f); - QVERIFY(f1 == 0.5); - QVERIFY(f1.numerator() == 1); - QVERIFY(f1.denominator() == 2); + // Normal fraction + Fraction f1 = Fraction(1, 2); + QCOMPARE(f1.getNumerator(), 1); + QCOMPARE(f1.getDenominator(), 2); - Fraction f2 = Fraction(2,4); - QVERIFY(f1 == f2); - QVERIFY(f2 == 0.5f); - QVERIFY(f2 == 0.5); - QVERIFY(f2.numerator() == 1); - QVERIFY(f2.denominator() == 2); + // Reducible fraction + Fraction f2 = Fraction(2,4); + QCOMPARE(f2.getNumerator(), 1); + QCOMPARE(f2.getDenominator(), 2); + + // Negative fractions + Fraction f3 = Fraction(-1, 3); + QCOMPARE(f3.getNumerator(), -1); + QCOMPARE(f3.getDenominator(), 3); + + Fraction f4 = Fraction(1, -3); + QCOMPARE(f4.getNumerator(), -1); + QCOMPARE(f4.getDenominator(), 3); + + // Double negative (positive) fraction + Fraction f5 = Fraction(-2, -3); + QCOMPARE(f5.getNumerator(), 2); + QCOMPARE(f5.getDenominator(), 3); +} + +void FractionTest::test_display() +{ + // Normal fraction + Fraction f1 = Fraction(1, 2); + QCOMPARE(f1.display(), "1/2"); + Fraction f2 = Fraction(1, 3); + QCOMPARE(f2.display(), "1/3"); + + // Fractions that reduce + Fraction f3 = Fraction(2, 4); + QCOMPARE(f3.display(), "1/2"); + Fraction f4 = Fraction(982929, 123456); + QCOMPARE(f4.display(), "327643/41152"); + + // Negative Fractions + Fraction f5 = Fraction(-5, 2); + QCOMPARE(f5.display(), "-5/2"); } void FractionTest::test_equivalence() { - Fraction f1 = Fraction(1, 1); - Fraction f2 = Fraction(1, 1); - QVERIFY(f1 == f2); + Fraction f1 = Fraction(1, 1); + Fraction f2 = Fraction(1, 1); + Fraction f3 = Fraction(-1, 1); - QVERIFY(f1 == 1); - QVERIFY(f1 == 1.0); - QVERIFY(f1 == 1.0f); + QCOMPARE(f1, f2); - QVERIFY(f2 == 1); - QVERIFY(f2 == 1.0); - QVERIFY(f2 == 1.0f); + QCOMPARE(f1, 1); + QCOMPARE(f1, 1.0); + QCOMPARE(f1, 1.0f); - Fraction f3 = Fraction(2, 3); - QVERIFY(f3 != 1); - QVERIFY(f3 != 1.0); - QVERIFY(f3 != 1.0f); + QCOMPARE(f2, 1); + QCOMPARE(f2, 1.0); + QCOMPARE(f2, 1.0f); + + QCOMPARE(f3, -1); + QCOMPARE(f3, -1.0); + QCOMPARE(f3, -1.0f); +} +void FractionTest::test_inequivalence() { + Fraction f1 = Fraction(1, 1); + Fraction f2 = Fraction(-1, 1); + Fraction f3 = Fraction(2, 3); + QVERIFY(f1 != f2); + QVERIFY(f2 != f3); + QVERIFY(f3 != f1); + + QVERIFY(f3 != 1); + QVERIFY(f3 != 1.0); + QVERIFY(f3 != 1.0f); +} + +void FractionTest::test_addition() +{ + Fraction f1 = Fraction(1, 2); + QCOMPARE(f1 + 1.0f, 1.5f); + f1 += 1.0f; + QCOMPARE(f1, 1.5); + + Fraction f2 = Fraction(1, 2); + QCOMPARE(f2 + 1.0f, 1.5f); + QCOMPARE(f2, 1.0f); } QTEST_APPLESS_MAIN(FractionTest)