From e55d2843f6e4feb0a29e7360caca8a19e59963cf Mon Sep 17 00:00:00 2001 From: Tobias Berger Date: Mon, 20 Sep 2021 16:34:45 +0200 Subject: [PATCH] Addition --- FractionTask.pro.user | 159 ++++++++++++------------------------------ fraction.cpp | 127 +++++++++++++++++++++++---------- fraction.hpp | 11 +-- tst_fractiontest.cpp | 58 +++++++++++++-- 4 files changed, 197 insertions(+), 158 deletions(-) diff --git a/FractionTask.pro.user b/FractionTask.pro.user index 782784a..aef6d40 100644 --- a/FractionTask.pro.user +++ b/FractionTask.pro.user @@ -1,10 +1,10 @@ - + EnvironmentId - {d3621eea-71f0-43b2-9e98-92c09a372104} + {02054f7f-15a3-41d0-aa9a-437b1d81f72b} ProjectExplorer.Project.ActiveTarget @@ -37,6 +37,7 @@ true true 1 + false true false 0 @@ -45,28 +46,48 @@ 0 8 true + false 1 true true true + *.md, *.MD, Makefile false + true ProjectExplorer.Project.PluginSettings + + true + false + true + true + true + true + + + Checked + Checked + Checked + Checked + Checked + Checked + + 0 + true -fno-delayed-template-parsing true - Builtin.Questionable + Builtin.BuildSystem + true true Builtin.DefaultTidyAndClazy 2 - - C:/Users/$5NP000-N4QVBFC8R26B/Documents/FractionTask/FractionTask.pro - + true @@ -76,33 +97,27 @@ ProjectExplorer.Project.Target.0 - Desktop Qt 5.15.0 MinGW 64-bit - Desktop Qt 5.15.0 MinGW 64-bit - qt.qt5.5150.win64_mingw81_kit + Desktop + Desktop Qt 6.1.3 MinGW 64-bit + Desktop Qt 6.1.3 MinGW 64-bit + qt.qt6.613.win64_mingw81_kit 0 0 0 - true 0 - C:\Users\$5NP000-N4QVBFC8R26B\Documents\build-FractionTask-Desktop_Qt_5_15_0_MinGW_64_bit-Debug - C:/Users/$5NP000-N4QVBFC8R26B/Documents/build-FractionTask-Desktop_Qt_5_15_0_MinGW_64_bit-Debug + C:\Users\Berger.ASGARD\Documents\Git\build-FractionTask-Desktop_Qt_6_1_3_MinGW_64_bit-Debug + C:/Users/Berger.ASGARD/Documents/Git/build-FractionTask-Desktop_Qt_6_1_3_MinGW_64_bit-Debug true QtProjectManager.QMakeBuildStep - false true Qt4ProjectManager.MakeStep - - false - - - false 2 Erstellen @@ -113,11 +128,7 @@ true Qt4ProjectManager.MakeStep - - true clean - - false 1 Bereinigen @@ -126,34 +137,25 @@ 2 false + Debug Qt4ProjectManager.Qt4BuildConfiguration 2 - 2 - 2 - true - 2 - C:\Users\$5NP000-N4QVBFC8R26B\Documents\build-FractionTask-Desktop_Qt_5_15_0_MinGW_64_bit-Release - C:/Users/$5NP000-N4QVBFC8R26B/Documents/build-FractionTask-Desktop_Qt_5_15_0_MinGW_64_bit-Release + C:\Users\Berger.ASGARD\Documents\Git\build-FractionTask-Desktop_Qt_6_1_3_MinGW_64_bit-Release + C:/Users/Berger.ASGARD/Documents/Git/build-FractionTask-Desktop_Qt_6_1_3_MinGW_64_bit-Release true QtProjectManager.QMakeBuildStep - false true Qt4ProjectManager.MakeStep - - false - - - false 2 Erstellen @@ -164,11 +166,7 @@ true Qt4ProjectManager.MakeStep - - true clean - - false 1 Bereinigen @@ -177,34 +175,27 @@ 2 false + Release Qt4ProjectManager.Qt4BuildConfiguration 0 0 - 2 - true 0 - C:\Users\$5NP000-N4QVBFC8R26B\Documents\build-FractionTask-Desktop_Qt_5_15_0_MinGW_64_bit-Profile - C:/Users/$5NP000-N4QVBFC8R26B/Documents/build-FractionTask-Desktop_Qt_5_15_0_MinGW_64_bit-Profile + C:\Users\Berger.ASGARD\Documents\Git\build-FractionTask-Desktop_Qt_6_1_3_MinGW_64_bit-Profile + C:/Users/Berger.ASGARD/Documents/Git/build-FractionTask-Desktop_Qt_6_1_3_MinGW_64_bit-Profile true QtProjectManager.QMakeBuildStep - false true Qt4ProjectManager.MakeStep - - false - - - false 2 Erstellen @@ -215,11 +206,7 @@ true Qt4ProjectManager.MakeStep - - true clean - - false 1 Bereinigen @@ -228,6 +215,7 @@ 2 false + Profile Qt4ProjectManager.Qt4BuildConfiguration @@ -249,80 +237,21 @@ ProjectExplorer.DefaultDeployConfiguration 1 - - dwarf - - cpu-cycles - - - 250 - - -e - cpu-cycles - --call-graph - dwarf,4096 - -F - 250 - - -F true - 4096 - false - false - 1000 - true - - false - false - false - false - true - 0.01 - 10 - true - kcachegrind - 1 - 25 - - 1 true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - + 2 - Qt4ProjectManager.Qt4RunConfiguration:C:/Users/$5NP000-N4QVBFC8R26B/Documents/FractionTask/FractionTask.pro - C:/Users/$5NP000-N4QVBFC8R26B/Documents/FractionTask/FractionTask.pro - - false - + Qt4ProjectManager.Qt4RunConfiguration:C:/Users/Berger.ASGARD/Documents/Git/FractionTask/FractionTask.pro + C:/Users/Berger.ASGARD/Documents/Git/FractionTask/FractionTask.pro false true true - false false true - - C:/Users/$5NP000-N4QVBFC8R26B/Documents/build-FractionTask-Desktop_Qt_5_15_0_MinGW_64_bit-Debug + C:/Users/Berger.ASGARD/Documents/Git/build-FractionTask-Desktop_Qt_6_1_3_MinGW_64_bit-Debug 1 diff --git a/fraction.cpp b/fraction.cpp index d108eed..4e6cc11 100644 --- a/fraction.cpp +++ b/fraction.cpp @@ -3,12 +3,14 @@ namespace FractionNS { int gcd(int p, int q) { + if(p < 0) p = -p; + if(q < 0) q = -q; while(true) { - if(p == 0) return q; - q %= p; - if(q == 0) return p; - p %= q; - } + if(p == 0) return q; + q %= p; + if(q == 0) return p; + p %= q; + } } int lcm(int p, int q) { @@ -17,32 +19,36 @@ namespace FractionNS { return gcd != 0 ? (p / gcd * q) : 0; } - int abs(int n) { - if(n < 0) return -n; - return n; - } + void Fraction::reduce() + { + auto gcd = FractionNS::gcd(m_numerator, m_denominator); + if((gcd == 1 && m_denominator >= 0) || gcd == 0) return; + if(gcd == 1 && m_denominator < 0) { + m_numerator = -m_numerator; + m_denominator = -m_denominator; + } + else if(m_denominator < 0) + { + m_numerator = -m_numerator / gcd; + m_denominator = -m_denominator / gcd; + } else { + m_numerator /= gcd; + m_denominator /= gcd; + } + } 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; + if(denominator == 0) throw std::range_error("Tried to divide by 0."); + this->m_numerator = numerator; + this->m_denominator = denominator; + reduce(); } - Fraction::Fraction(int n) { + Fraction::Fraction(const int n) { this->m_numerator = n; this->m_denominator = 1; } - Fraction::Fraction(float n) { - // TODO - throw std::runtime_error("Not yet implemented"); - } Fraction::Fraction(const Fraction& n) { this->m_numerator = n.getNumerator(); this->m_denominator = n.getDenominator(); @@ -52,11 +58,12 @@ namespace FractionNS { int Fraction::getDenominator() const { return m_denominator; } void Fraction::setNumerator(int numerator) { - auto gcd = std::__gcd(numerator, this->m_denominator); + auto gcd = FractionNS::gcd(numerator, this->m_denominator); this->m_numerator = numerator / gcd; } void Fraction::setDenominator(int denominator) { - auto gcd = std::__gcd(this->m_numerator, denominator); + if(denominator == 0) throw std::range_error("Tried to divide by 0."); + auto gcd = FractionNS::gcd(this->m_numerator, denominator); this->m_denominator = denominator / gcd; } @@ -68,7 +75,7 @@ namespace FractionNS { return (double(m_numerator) / double(m_denominator)) == n; } bool Fraction::operator==(const float n) const { - return (double(m_numerator) / double(m_denominator)) == n; + return (float(m_numerator) / float(m_denominator)) == n; } bool Fraction::operator==(const double n) const { return (double(m_numerator) / double(m_denominator)) == n; @@ -93,16 +100,66 @@ namespace FractionNS { } 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; + auto newNumerator = m_numerator + (n * m_denominator); + return *new Fraction(newNumerator, m_denominator); } Fraction& Fraction::operator+(const Fraction& other) const { - auto lcm = FractionNS::lcm(getDenominator(), other.getDenominator()); - return *new Fraction((getNumerator() + other.getNumerator()) * lcm, getDenominator() * lcm); + auto lcm = FractionNS::lcm(m_denominator, other.getDenominator()); + + auto ownNumeratorPart = m_numerator * (lcm / m_denominator); + auto otherNumeratorPart = other.getNumerator() * (lcm / other.getDenominator()); + + return *new Fraction(ownNumeratorPart + otherNumeratorPart, lcm); + } + + Fraction& Fraction::operator+=(const int other) { + this->m_numerator = m_numerator + (other * m_denominator); + reduce(); + return *this; + } + Fraction& Fraction::operator+=(const Fraction& other) { + // Sanity check for Clang + // Not strictly necessary since setting to 0 is checked against in setDenominator and constructor(s). + if(other.getDenominator() == 0) return *this; + + auto lcm = FractionNS::lcm(m_denominator, other.getDenominator()); + + auto ownNumeratorPart = m_numerator * (lcm / m_denominator); + auto otherNumeratorPart = other.getNumerator() * (lcm / other.getDenominator()); + + this->m_numerator = ownNumeratorPart + otherNumeratorPart; + this->m_denominator = lcm; + + reduce(); + return *this; + } + + Fraction& Fraction::operator-(const int n) const { + auto newNumerator = m_numerator - (n * m_denominator); + return *new Fraction(newNumerator, m_denominator); + }; + Fraction& Fraction::operator-(const Fraction& other) const { + auto lcm = FractionNS::lcm(m_denominator, other.getDenominator()); + + auto ownNumeratorPart = m_numerator * (lcm / m_denominator); + auto otherNumeratorPart = other.getNumerator() * (lcm / other.getDenominator()); + + return *new Fraction(ownNumeratorPart - otherNumeratorPart, lcm); + } + + Fraction& Fraction::operator-=(const int n) { + auto newNumerator = m_numerator - (n * m_denominator); + return *new Fraction(newNumerator, m_denominator); + }; + Fraction& Fraction::operator-=(const Fraction& other) { + // Sanity check for Clang + // Not strictly necessary since setting to 0 is checked against in setDenominator and constructor(s). + if(other.getDenominator() == 0) return *this; + auto lcm = FractionNS::lcm(m_denominator, other.getDenominator()); + + auto ownNumeratorPart = m_numerator * (lcm / m_denominator); + auto otherNumeratorPart = other.getNumerator() * (lcm / other.getDenominator()); + + return *new Fraction(ownNumeratorPart - otherNumeratorPart, lcm); } } diff --git a/fraction.hpp b/fraction.hpp index fbcf81d..520758a 100644 --- a/fraction.hpp +++ b/fraction.hpp @@ -7,6 +7,7 @@ namespace FractionNS { { private: int m_numerator, m_denominator; + void reduce(); public: Fraction(int, int); Fraction(int); @@ -32,13 +33,15 @@ namespace FractionNS { 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&); + + Fraction& operator-(const int) const; + Fraction& operator-(const Fraction&) const; + + Fraction& operator-=(const int); + Fraction& operator-=(const Fraction&); }; } diff --git a/tst_fractiontest.cpp b/tst_fractiontest.cpp index 2c23836..b7f9b5f 100644 --- a/tst_fractiontest.cpp +++ b/tst_fractiontest.cpp @@ -1,4 +1,5 @@ #include +#include #include "fraction.hpp" @@ -18,6 +19,7 @@ private slots: void test_equivalence(); void test_addition(); void test_inequivalence(); + void test_substraction(); }; FractionTest::FractionTest() @@ -95,11 +97,33 @@ void FractionTest::test_equivalence() QCOMPARE(f3, -1); QCOMPARE(f3, -1.0); QCOMPARE(f3, -1.0f); + + Fraction f4 = Fraction(2, 3); + Fraction f5 = Fraction(-2, 3); + Fraction f6 = Fraction(2, -3); + Fraction f7 = Fraction(-2, -3); + + QCOMPARE(f4, f7); + QCOMPARE(f5, f6); + + QCOMPARE(f4, 2.0f/3.0f); + QCOMPARE(f4, 2.0/3.0); + + QCOMPARE(f7, 2.0f/3.0f); + QCOMPARE(f7, 2.0/3.0); + + QCOMPARE(f5, -2.0f/3.0f); + QCOMPARE(f5, -2.0/3.0); + + QCOMPARE(f6, -2.0f/3.0f); + QCOMPARE(f6, -2.0/3.0); } + 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); @@ -112,13 +136,39 @@ void FractionTest::test_inequivalence() { void FractionTest::test_addition() { Fraction f1 = Fraction(1, 2); - QCOMPARE(f1 + 1.0f, 1.5f); - f1 += 1.0f; + QCOMPARE(f1 + 1, 1.5f); + QCOMPARE(f1, 0.5f); + f1 += 1; QCOMPARE(f1, 1.5); Fraction f2 = Fraction(1, 2); - QCOMPARE(f2 + 1.0f, 1.5f); - QCOMPARE(f2, 1.0f); + QCOMPARE(f2 + 1, 1.5f); + QCOMPARE(f2, 0.5f); + + Fraction f3 = Fraction(-2, 9); + QCOMPARE(f3, -(2.0/9.0)); + QCOMPARE(f3, -(2.0f/9.0f)); + f3 += Fraction(2, 9); + QCOMPARE(f3, 0); + QCOMPARE(f3, 0.0); + QCOMPARE(f3, 0.0f); +} + +void FractionTest::test_substraction() { + Fraction f1 = Fraction(11) - 10; + QCOMPARE(f1, 1); + + Fraction f2 = Fraction(2, 3); + QCOMPARE(f1 - f2, Fraction(1, 3)); + QCOMPARE(f2 - f1, Fraction(-1, 3)); + + Fraction f3 = Fraction(8, 3); + f3 -= Fraction(2, 3); + QCOMPARE(f3, Fraction(6, 3)); + + Fraction f4 = Fraction(9, 3); + f4 -= 3; + QCOMPARE(f4, 0); } QTEST_APPLESS_MAIN(FractionTest)