Skip to content

Instantly share code, notes, and snippets.

@e5l
Created November 16, 2017 15:17
Show Gist options
  • Save e5l/95f0abbaeecc5f6b7c5cf066414e26c2 to your computer and use it in GitHub Desktop.
Save e5l/95f0abbaeecc5f6b7c5cf066414e26c2 to your computer and use it in GitHub Desktop.
Rational
#pragma once
#include <iostream>
#include <cstdlib>
class rational;
bool operator==(const rational &lhs, const rational &rhs);
bool operator!=(const rational &lhs, const rational &rhs);
bool operator<(const rational &lhs, const rational &rhs);
bool operator<=(const rational &lhs, const rational &rhs);
bool operator>=(const rational &lhs, const rational &rhs);
bool operator>(const rational &lhs, const rational &rhs);
rational operator+(const rational &lhs, const rational &rhs);
rational operator-(const rational &lhs, const rational &rhs);
rational operator*(const rational &lhs, const rational &rhs);
rational operator/(const rational &lhs, const rational &rhs);
class rational
{
public:
/* минимально необходимый набор методов */
rational(int number)
: rational(number, 1)
{}
rational(int nominator, unsigned int denominator)
: _nominator(nominator)
, _denominator(denominator)
{
simplify();
}
/* прибавить текущее к переданному */
rational &add(const rational &other)
{
_nominator = _nominator * other.denominator() + _denominator * other._nominator;
_denominator *= other._denominator;
simplify();
return *this;
}
rational &operator+=(const rational &other)
{
return add(other);
}
rational &operator-=(const rational &other)
{
return add(rational(other).negate());
}
/* умножить текущее на переданное */
rational &multiply(const rational &other)
{
_nominator *= other._nominator;
_denominator *= other._denominator;
simplify();
return *this;
}
rational &operator*=(const rational &other)
{
return multiply(other);
}
rational &operator/=(const rational &other)
{
return multiply(1 / other);
}
/* изменить знак числа */
rational &negate()
{
_nominator *= -1;
simplify();
return *this;
}
/* проверить равны ли два числа */
bool equals(const rational &other) const
{
return _nominator == other._nominator && _denominator == other._denominator;
}
/* проверить правда ли что текущее число меньше переданного */
bool less(const rational &other) const
{
rational left = *this;
rational right = other;
return left.add(right.negate()).negative();
}
/* проверить отрицательность числа */
bool negative() const
{
return _nominator < 0;
}
/* числитель */
unsigned int nominator() const
{
return negative() ? -_nominator : _nominator;
}
/* знаменатель */
unsigned int denominator() const
{
return _denominator;
}
/* выделить целую часть(округлить в сторону нуля) */
int toInt() const
{
return std::div(_nominator, _denominator).quot;
}
rational operator-()
{
return rational(*this).negate();
}
rational &operator++()
{
add(1);
return *this;
}
rational operator++(int)
{
rational result(*this);
add(1);
return result;
}
rational &operator--()
{
add(-1);
return *this;
}
rational operator--(int)
{
rational result(*this);
add(-1);
return result;
}
explicit operator int()
{
return toInt();
}
private:
int _nominator;
unsigned int _denominator;
void simplify()
{
unsigned int nominator = (_nominator < 0) ? -_nominator : _nominator;
int divisor = gcd(nominator, _denominator);
_nominator /= divisor;
_denominator /= divisor;
if (_nominator == 0) _denominator = 1;
}
int gcd(int a, int b)
{
if (b == 0) return a;
return gcd(b, a % b);
}
};
inline bool operator==(const rational &lhs, const rational &rhs)
{
return lhs.equals(rhs);
}
inline bool operator!=(const rational &lhs, const rational &rhs)
{
return !lhs.equals(rhs);
}
inline bool operator<(const rational &lhs, const rational &rhs)
{
return lhs.less(rhs);
}
inline bool operator<=(const rational &lhs, const rational &rhs)
{
return lhs < rhs || lhs == rhs;
}
inline bool operator>=(const rational &lhs, const rational &rhs)
{
return !lhs.less(rhs);
}
inline bool operator>(const rational &lhs, const rational &rhs)
{
return lhs >= rhs && lhs != rhs;
}
inline rational operator+(const rational &lhs, const rational &rhs)
{
return rational(lhs).add(rhs);
}
inline rational operator-(const rational &lhs, const rational &rhs)
{
return rational(lhs).add(rational(rhs).negate());
}
inline rational operator*(const rational &lhs, const rational &rhs)
{
return rational(lhs).multiply(rhs);
}
inline rational operator/(const rational &lhs, const rational &rhs)
{
int nominator = rhs.denominator() * (rhs.negative() ? -1 : 1);
unsigned int denominator = rhs.nominator() * (rhs.negative() ? -1 : 1);
return rational(lhs).multiply(rational(nominator, denominator));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment