class Rational
{
static inline int gcd(int a, int b)
{
if (!b) return abs(a);
while ((a %= b) && (b %= a)) ; // do in while
return a + b;
}
public:
static const Rational Infinity;
static const Rational Nan;
Rational(int numerator, int denominator)
: n(numerator), d(denominator) { symplify(); }
constexpr Rational(int number) : n(number), d(1) {}
constexpr Rational() : n(0), d(1) {}
const Rational &operator=(const Rational &other)
{
n = other.n;
d = other.d;
return *this;
}
const int numerator() const { return n; }
const int denominator() const { return d; }
private:
void symplify()
{
int cd = gcd(n, d);
if (cd) {
n /= cd;
d /= cd;
}
if (d < 0) {
n = -n;
d = -d;
}
}
int n, d;
};
const Rational Rational::Infinity = Rational(1, 0);
const Rational Rational::Nan = Rational(0, 0);
inline const Rational operator-(const Rational &a)
{ return Rational(-a.numerator(), a.denominator()); }
inline const Rational operator+(const Rational &a, const Rational &b)
{
return Rational(a.numerator() * b.denominator() +
a.denominator() * b.numerator(),
a.denominator() * b.denominator());
}
inline const Rational operator-(const Rational &a, const Rational &b)
{ return a + -b; }
inline const Rational operator*(const Rational &a, const Rational &b)
{
return Rational(a.numerator() * b.numerator(),
a.denominator() * b.denominator());
}
inline const Rational operator/(const Rational &a, const Rational &b)
{
return Rational(a.numerator() * b.denominator(),
a.denominator() * b.numerator());
}
std::ostream &operator<<(std::ostream &os, const Rational &r)
{
switch (r.denominator())
{
case 0:
if (r.numerator() == 0) return os << "NaN";
if (r.numerator() < 0) os << '-';
return os << "Inf";
case 1:
return os << r.numerator();
default:
return os << '(' << r.numerator() << '/' << r.denominator() << ')';
}
}
void test_rational()
{
Rational a(6, -2);
cout << a << '\n';
cout << Rational(9, 33) + 5 << '\n';
cout << Rational(-9, 33) * 2 << '\n';
cout << Rational(-9, -33) - 1 << '\n';
cout << Rational(9, -33) / 8 << '\n';
cout << 1 / Rational(9, -33) << '\n';
cout << "-----Inf------\n";
cout << a * -Rational::Infinity << '\n';
cout << a * - -Rational::Infinity << '\n';
cout << a + Rational::Infinity << '\n';
cout << a - Rational::Infinity << '\n';
cout << "-----NaN------\n";
cout << Rational::Nan - Rational::Infinity << '\n';
cout << a * Rational::Nan << '\n';
cout << a / Rational::Nan << '\n';
cout << a + Rational::Nan << '\n';
cout << a - Rational::Nan << '\n';
}