#include <iostream>
#include <math>

class Ulamek
  {
   private:
   long L,M;
   static long NWD(long A,long B);
   void Normalizuj();
   public:
   Ulamek():L(0),M(1) {}
   Ulamek(long L,long M):L(L),M(M) { Normalizuj(); }
   long l()const { return L; }
   long m()const { return M; }
   Ulamek operator-(const Ulamek &B)const;
   Ulamek operator+(const Ulamek &B)const;
   Ulamek operator*(const Ulamek &B)const;
   Ulamek operator/(const Ulamek &B)const;
   Ulamek operator-()const { return Ulamek(-L,M); }
   Ulamek &operator++();
   Ulamek operator++(int);
   Ulamek &operator--();
   Ulamek operator--(int);
   Ulamek &operator()(long L,long M);
   Ulamek operator+(long X)const;
   Ulamek operator-(long X)const;
   Ulamek operator*(long X)const;
   Ulamek operator/(long X)const;
   operator double()const;
  };

long Ulamek::NWD(long A,long B)
  {
   while(B)
     {

      long R=A%B;
      A=B;
      B=R;
     }
   return A?A:1;
  }

void Ulamek::Normalizuj()
  {
   if(M<0) { L=-L; M=-M; }
   long D=NWD(abs(L),M);
   L/=D;
   M/=D;
  }

Ulamek Ulamek::operator-(const Ulamek &B)const
  {
   return Ulamek(L*B.M-B.L*M,M*B.M);
  }

Ulamek Ulamek::operator+(const Ulamek &B)const
  {
   return Ulamek(L*B.M+B.L*M,M*B.M);
  }

Ulamek Ulamek::operator*(const Ulamek &B)const
  {
   return Ulamek(L*B.L,M*B.M);
  }

Ulamek Ulamek::operator/(const Ulamek &B)const
  {
   return Ulamek(L*B.M,M*B.L);
  }

Ulamek &Ulamek::operator++()
  {
   L+=M;
   Normalizuj();
   return *this;
  }

Ulamek Ulamek::operator++(int)
  {
   long Ltmp=L,Mtmp=M;
   L+=M;
   Normalizuj();
   return Ulamek(Ltmp,Mtmp);
  }

Ulamek &Ulamek::operator--()
  {
   L-=M;
   Normalizuj();
   return *this;
  }

Ulamek Ulamek::operator--(int)
  {
   long Ltmp=L,Mtmp=M;
   L-=M;
   Normalizuj();
   return Ulamek(Ltmp,Mtmp);
  }

inline Ulamek Ulamek::operator+(long X)const
  {
   return Ulamek(L+X*M,M);
  }

inline Ulamek Ulamek::operator-(long X)const
  {
   return Ulamek(L-X*M,M);
  }

inline Ulamek Ulamek::operator*(long X)const
  {
   return Ulamek(L*X,M);
  }

inline Ulamek Ulamek::operator/(long X)const
  {
   return Ulamek(L,M*X);
  }

Ulamek &Ulamek::operator()(long L,long M)
  {
   Ulamek::L=L;
   Ulamek::M=M;
   Normalizuj();
   return *this;
  }

Ulamek::operator double()const
  {
   if(!M) throw "Zerowy mianownik";
   return (double)L/M;
  }

inline double operator+(double X,const Ulamek &u)
  {
   return X+u;
  }

inline double operator-(double X,const Ulamek &u)
  {
   return X-u;
  }

inline double operator*(double X,const Ulamek &u)
  {
   return X*u;
  }

inline double operator/(double X,const Ulamek &u)
  {
   return X/u;
  }

ostream &operator<<(ostream &out,const Ulamek &u)
  {
   return out<<u.l()<<'/'<<u.m();
  }

istream &operator>>(istream &in,Ulamek &u)
  {
   long L,M;
   char C;
   in>>L>>C>>M;
   if((in)&&(C=='/')) u(L,M);
   return in;
  }

int main()
  {
   Ulamek A(1,2),B(3,4),C,D;

   C=A+B;
   D=A-B;

   cout<<A<<'+'<<B<<'='<<C<<';'<<endl;
   cout<<A<<'-'<<B<<'='<<D<<';'<<endl;
   cout<<(-D)<<endl;
   A(5,6);

   cout<<"Wprowadz ulamek (np 4/5): ";
   cin>>C;
   cout<<C<<endl;

   try
     {
      cout<<C<<'='<<(double)C<<endl;
     }
   catch(char *msg)
     {
      cout<<"Blad: "<<msg<<endl;
     }

   cin.ignore(1024,'\n');
   cin.get();
   return 0;
  }
