geekbrains_oop_cpp/lesson_3/exercise_3.hpp

226 lines
4.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef EXERCISE_3_HPP_
#define EXERCISE_3_HPP_
#include <iostream>
class Fraction
{
private:
bool is_zero;
bool is_integer;
int numerator;
int denominator;
/*
* Поиск наибольшего общего делителя
* для числителя и знаменателя
*/
int NOD(int n1, int n2)
{
int div;
if (n1 == n2) return n1;
int d = n1 - n2;
if (d < 0)
{
d = -d;
div = NOD(n1, d);
}
else
div = NOD(n2, d);
return div;
}
/*
* Поиск наименьшего общего кратного
* для знаменателей
*/
int NOK(int n1, int n2)
{
return n1 * n2 / NOD(n1, n2);
}
/*
* Функция сокращения дроби
*/
void reduceFraction(int& a, int& b)
{
int divisor = NOD(abs(a), abs(b));
a = a / divisor;
b = b / divisor;
}
public:
Fraction () : numerator(0), denominator(0)
{
is_zero = true;
is_integer = true;
}
Fraction(int num, int dnum) : numerator(num), denominator(dnum)
{
if (numerator == 0 || denominator == 0)
{
std::cout << "Числитель или знаменатель не может быть нулевым!\n"
<< "Число будет инициализировано нулём!" << std::endl;
numerator = 0;
denominator = 0;
is_zero = true;
is_integer = true;
}
else
{
is_zero = false;
is_integer = (abs(numerator) == abs(denominator) || denominator == 1);
}
}
friend std::ostream& operator<<(std::ostream&, const Fraction&);
Fraction operator+(const Fraction&);
Fraction operator-(const Fraction&);
Fraction operator*(const Fraction&);
Fraction operator/(const Fraction&);
Fraction operator-() const;
bool operator==(const Fraction&);
bool operator!=(const Fraction&);
bool operator<(const Fraction&);
bool operator>=(const Fraction&);
bool operator>(const Fraction&);
bool operator<=(const Fraction&);
};
std::ostream& operator<<(std::ostream& s, const Fraction& f)
{
if (f.is_integer)
{
if (f.is_zero)
s << f.numerator;
else
s << f.numerator / f.denominator;
}
else
s << f.numerator << '/' << f.denominator;
return s;
}
Fraction Fraction::operator+(const Fraction& f)
{
if (f.is_zero)
return Fraction(numerator, denominator);
if (is_zero)
return Fraction(f.numerator, f.denominator);
int new_denominator = NOK(denominator, f.denominator);
int new_numerator = numerator * (new_denominator / denominator) + f.numerator * (new_denominator / f.denominator);
reduceFraction(new_numerator, new_denominator);
return Fraction(new_numerator, new_denominator);
}
Fraction Fraction::operator-(const Fraction& f)
{
if (f.is_zero)
return Fraction(numerator, denominator);
if (is_zero)
return Fraction(-f.numerator, f.denominator);
int new_denominator = NOK(denominator, f.denominator);
int new_numerator = numerator * (new_denominator / denominator) - f.numerator * (new_denominator / f.denominator);
if (new_numerator == 0)
return Fraction();
reduceFraction(new_numerator, new_denominator);
return Fraction(new_numerator, new_denominator);
}
Fraction Fraction::operator*(const Fraction& f)
{
if (is_zero || f.is_zero)
return Fraction();
int new_numerator = numerator * f.numerator;
int new_denominator = denominator * f.denominator;
reduceFraction(new_numerator, new_denominator);
return Fraction(new_numerator, new_denominator);
}
Fraction Fraction::operator/(const Fraction& f)
{
if (f.is_zero)
{
std::cout << " [На 0 делить нельзя!] ";
return Fraction();
}
if (is_zero)
return Fraction();
return *this * Fraction(f.denominator, f.numerator);
}
Fraction Fraction::operator-() const
{
return Fraction(-numerator, denominator);
}
bool Fraction::operator==(const Fraction& f)
{
if (is_zero || f.is_zero)
return numerator == f.numerator;
int a_n = numerator;
int a_d = denominator;
int b_n = f.numerator;
int b_d = f.denominator;
reduceFraction(a_n, a_d);
reduceFraction(b_n, b_d);
return a_n == b_n && a_d == b_d;
}
bool Fraction::operator!=(const Fraction& f)
{
return !(*this == f);
}
bool Fraction::operator<(const Fraction& f)
{
if (is_zero || f.is_zero)
return numerator < f.numerator;
int new_denominator = NOK(denominator, f.denominator);
int a_n = numerator * (new_denominator / denominator);
int b_n = f.numerator * (new_denominator / f.denominator);
return a_n < b_n;
}
bool Fraction::operator>=(const Fraction& f)
{
return (*this == f || !(*this < f));
}
bool Fraction::operator>(const Fraction& f)
{
return (*this != f && !(*this < f));
}
bool Fraction::operator<=(const Fraction& f)
{
return (*this == f || *this < f);
}
#endif