#include<iostream>
#include<climits>
using namespace std;
class bad_rational{};
class rational
{
int num; //любое целое
int denom;//должен быть >0
void normalize();
public:
rational():num(0),denom(1){}
rational(int n):num(n),denom(1){}
rational(int n,int d);
int numerator() const {return num;}
int denominator() const {return denom;}
rational& reduce();
rational get_reduced()const;
// Операторы сравнения
bool operator< (const rational& r) const;
bool operator<= (const rational& r) const;
bool operator> (const rational& r) const;
bool operator>= (const rational& r) const;
bool operator== (const rational& r) const;
bool operator!= (const rational& r) const;
// Арифметические операторы
rational& operator+= (const rational& r);
rational& operator-= (const rational& r);
rational& operator*= (const rational& r);
rational& operator/= (const rational& r);
// Арифметические операторы с целыми параметрами
/*rational& operator+= (int i);
rational& operator-= (int i);
rational& operator*= (int i);
rational& operator/= (int i);*/
//Присваивание целого числа
rational& operator=(int n){num=n;denom=1;}
friend istream& operator>> (istream& in, rational& r);
};
int gcd(int a, int b)
{
if (a<0) a=-a;
if (b<0) b=-b;
while (b!=0)
{
int p=a%b;
a=b;
b=p;
}
return a;
}
long long gcd(long long a, long long b)
{
if (a<0) a=-a;
if (b<0) b=-b;
while (b!=0)
{
long long p=a%b;
a=b;
b=p;
}
return a;
}
long long NOK(int a, int b)
{
return (long long)a/gcd(a,b)*b;
}
void rational::normalize()
{
if (denom==0) throw bad_rational();
if (denom<0){num=-num;denom=-denom;}
}
rational::rational(int n,int d):num(n),denom(d)
{
normalize();
}
rational& rational::reduce()
{
int d=gcd(num,denom);
num/=d;
denom/=d;
return (*this);
}
rational rational::get_reduced()const
{
int d=gcd(num,denom);
return rational(num/d,denom/d);
}
bool rational::operator< (const rational& r) const
{
return (long long)this->num*r.denom<(long long)r.num*this->denom;
}
bool rational::operator<= (const rational& r) const
{
return (long long)this->num*r.denom<=(long long)r.num*this->denom;
}
bool rational::operator> (const rational& r) const
{
return (long long)this->num*r.denom>(long long)r.num*this->denom;
}
bool rational::operator>= (const rational& r) const
{
return (long long)this->num*r.denom>=(long long)r.num*this->denom;
}
bool rational::operator== (const rational& r) const
{
return (long long)this->num*r.denom==(long long)r.num*this->denom;
}
bool rational::operator!= (const rational& r) const
{
return (long long)this->num*r.denom!=(long long)r.num*this->denom;
}
rational& rational::operator+= (const rational& r)
{
long long new_denom=(long long)this->denom*r.denom;
long long new_num=(long long)this->num*r.denom+(long long)r.num*this->denom;
long long d=gcd(new_denom,new_num);
new_denom/=d;
new_num/=d;
if (new_denom>INT_MAX || abs(new_num)>INT_MAX) throw bad_rational();
denom=new_denom;
num=new_num;
return *this;
}
rational& rational::operator-= (const rational& r)
{
long long new_denom=(long long)this->denom*r.denom;
long long new_num=(long long)this->num*r.denom-(long long)r.num*this->denom;
long long d=gcd(new_denom,new_num);
new_denom/=d;
new_num/=d;
if (new_denom>INT_MAX || abs(new_num)>INT_MAX) throw bad_rational();
denom=new_denom;
num=new_num;
return *this;
}
rational& rational::operator*= (const rational& r)
{
return *this;
}
rational& rational::operator/= (const rational& r)
{
return *this;
}
rational operator-(const rational& r)
{
return rational(-r.numerator(),r.denominator());
}
rational operator+(const rational& r1,const rational& r2)
{
rational res(r1);
res+=r2;
return res;
}
rational operator+(int i,const rational& r2)
{
rational res(i);
res+=r2;
return res;
}
rational operator+(const rational& r1,int i)
{
rational res(r1);
res+=i;
return res;
}
rational operator-(const rational& r1,const rational& r2)
{
rational res(r1);
res-=r2;
return res;
}
rational operator-(int i,const rational& r2)
{
rational res(i);
res-=r2;
return res;
}
rational operator-(const rational& r1,int i)
{
rational res(r1);
res-=i;
return res;
}
istream& operator>> (istream& in, rational& r)
{
in>>r.num; in.ignore(2,'/'); in>>r.denom;
r.normalize();
}
ostream& operator<< (ostream& out, const rational& r)
{
out <<r.numerator()<<"/"<<r.denominator();
return out;
}
int main()
{
rational r13(1,3), r24(2,4);
cout <<r13 <<"+" <<r24 <<"=" <<r13+r24<<endl;
cout <<r13 <<"-" <<r24 <<"=" <<r13-r24<<endl;
try
{
rational qqq(1,2147483647), zzz(2,2147483645);
cout <<qqq <<"+" <<zzz <<"=" <<qqq+zzz<<endl;
}
catch(bad_rational&)
{
cout <<"Bad rational obtained!"<<endl;
}
return 0;
}