public class Rational extends Number implements Comparable<Rational> {
  // Pola z licznikiem i mianownikiem
  private long numerator = 0;
  private long denominator = 1;

  /** Tworzy liczbę wymierną z domyślnymi wartościami pól */
  public Rational() {
    this(0, 1);
  }

  /** Tworzy liczbę wymierną o określonym liczniku i mianowniku */
  public Rational(long numerator, long denominator) {
    long gcd = gcd(numerator, denominator);
    this.numerator = (denominator > 0 ? 1 : -1) * numerator / gcd;
    this.denominator = Math.abs(denominator) / gcd;
  }

  /** Znajduje największy wspólny dzielnik dwóch liczb */
  private static long gcd(long n, long d) {
    long n1 = Math.abs(n);
    long n2 = Math.abs(d);
    int gcd = 1;
    
    for (int k = 1; k <= n1 && k <= n2; k++) {
      if (n1 % k == 0 && n2 % k == 0) 
        gcd = k;
    }

    return gcd;
  }

  /** Zwraca licznik */
  public long getNumerator() {
    return numerator;
  }

  /** Zwraca mianownik */
  public long getDenominator() {
    return denominator;
  }

  /** Dodawanie drugiej liczby wymiernej do danej liczby */
  public Rational add(Rational secondRational) {
    long n = numerator * secondRational.getDenominator() +
      denominator * secondRational.getNumerator();
    long d = denominator * secondRational.getDenominator();
    return new Rational(n, d);
  }

  /** Odejmowanie drugiej liczby wymiernej od danej liczby */
  public Rational subtract(Rational secondRational) {
    long n = numerator * secondRational.getDenominator()
      - denominator * secondRational.getNumerator();
    long d = denominator * secondRational.getDenominator();
    return new Rational(n, d);
  }

  /** Mnożenie drugiej liczby wymiernej przez daną liczbę */
  public Rational multiply(Rational secondRational) {
    long n = numerator * secondRational.getNumerator();
    long d = denominator * secondRational.getDenominator();
    return new Rational(n, d);
  }

  /** Dzielenie drugiej liczby wymiernej przez daną liczbę */
  public Rational divide(Rational secondRational) {
    long n = numerator * secondRational.getDenominator();
    long d = denominator * secondRational.numerator;
    return new Rational(n, d);
  }

  @Override 
  public String toString() {
    if (denominator == 1)
      return numerator + "";
    else
      return numerator + "/" + denominator;
  }

  @Override // Przesłanianie metody equals z klasy Object 
  public boolean equals(Object other) {
    if ((this.subtract((Rational)(other))).getNumerator() == 0)
      return true;
    else
      return false;
  }

  @Override // Implementacja abstrakcyjnej metody intValue z klasy Number
  public int intValue() {
    return (int)doubleValue();
  }

  @Override // Implementacja abstrakcyjnej metody floatValue z klasy Number
  public float floatValue() {
    return (float)doubleValue();
  }

  @Override // Implementacja metody doubleValue z klasy Number
  public double doubleValue() {
    return numerator * 1.0 / denominator;
  }

  @Override // Implementacja abstrakcyjnej metody longValue z klasy Number
  public long longValue() {
    return (long)doubleValue();
  }

  @Override // Implementacja metody compareTo z interfejsu Comparable
  public int compareTo(Rational o) {
    if (this.subtract(o).getNumerator() > 0)
      return 1;
    else if (this.subtract(o).getNumerator() < 0)
      return -1;
    else
      return 0;
  }
}