This repository has been archived on 2021-09-24. You can view files and clone it, but cannot push or open issues or pull requests.
FractionTask/fraction.cpp

166 lines
5.3 KiB
C++
Raw Normal View History

2021-09-17 12:32:14 +02:00
#include "fraction.hpp"
2021-09-17 11:59:28 +02:00
2021-09-17 14:47:29 +02:00
namespace FractionNS {
int gcd(int p, int q) {
2021-09-20 16:34:45 +02:00
if(p < 0) p = -p;
if(q < 0) q = -q;
2021-09-17 14:47:29 +02:00
while(true) {
2021-09-20 16:34:45 +02:00
if(p == 0) return q;
q %= p;
if(q == 0) return p;
p %= q;
}
2021-09-17 14:47:29 +02:00
}
int lcm(int p, int q) {
int gcd = FractionNS::gcd(p, q);
return gcd != 0 ? (p / gcd * q) : 0;
}
2021-09-20 16:34:45 +02:00
void Fraction::reduce()
{
auto gcd = FractionNS::gcd(m_numerator, m_denominator);
if((gcd == 1 && m_denominator >= 0) || gcd == 0) return;
2021-09-17 14:47:29 +02:00
2021-09-20 16:34:45 +02:00
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;
}
}
2021-09-17 14:47:29 +02:00
Fraction::Fraction(int numerator, int denominator)
{
2021-09-20 16:34:45 +02:00
if(denominator == 0) throw std::range_error("Tried to divide by 0.");
this->m_numerator = numerator;
this->m_denominator = denominator;
reduce();
2021-09-17 14:47:29 +02:00
}
2021-09-20 16:34:45 +02:00
Fraction::Fraction(const int n) {
2021-09-17 14:52:24 +02:00
this->m_numerator = n;
this->m_denominator = 1;
}
Fraction::Fraction(const Fraction& n) {
this->m_numerator = n.getNumerator();
this->m_denominator = n.getDenominator();
}
2021-09-17 14:47:29 +02:00
int Fraction::getNumerator() const { return m_numerator; }
int Fraction::getDenominator() const { return m_denominator; }
void Fraction::setNumerator(int numerator) {
2021-09-20 16:34:45 +02:00
auto gcd = FractionNS::gcd(numerator, this->m_denominator);
2021-09-17 14:47:29 +02:00
this->m_numerator = numerator / gcd;
}
void Fraction::setDenominator(int denominator) {
2021-09-20 16:34:45 +02:00
if(denominator == 0) throw std::range_error("Tried to divide by 0.");
auto gcd = FractionNS::gcd(this->m_numerator, denominator);
2021-09-17 14:47:29 +02:00
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 {
2021-09-20 16:34:45 +02:00
return (float(m_numerator) / float(m_denominator)) == n;
2021-09-17 14:47:29 +02:00
}
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 {
2021-09-20 16:34:45 +02:00
auto newNumerator = m_numerator + (n * m_denominator);
return *new Fraction(newNumerator, m_denominator);
2021-09-17 14:47:29 +02:00
}
2021-09-20 16:34:45 +02:00
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);
2021-09-17 14:47:29 +02:00
}
2021-09-20 16:34:45 +02:00
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;
2021-09-17 14:47:29 +02:00
}
2021-09-20 16:34:45 +02:00
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);
2021-09-17 14:47:29 +02:00
}
2021-09-17 11:59:28 +02:00
}