分数クラス

30分プログラム、その736。演算子オーバーロードを使ってみたかったので、分数クラスを作ってみました。
テンプレートを使って、整数の分数とか浮動少数の分数とかできるのを目指してました。が、約分するときに%を使ってるので、int以外の型を引数として与えるとコンパイルエラーがでます。

使い方

rational<int> r1(1,2);
rational<int> r2(2,3);

cout << (r1 + r2) << endl; // => 7/6
cout << (r1 - r2) << endl; // => -1/6
cout << (r1 * r2) << endl; // => 1/3
cout << (r1 / r2) << endl; // => 3/4

ソースコード

#include <iostream>

template <class T>
class rational {
private:
  T num;
  T denom;

public:
  rational(T num, T denom) {
    T r =  gcd(num,denom);
    this->num = num / r;
    this->denom = denom / r;
  }

  T numerator() const {
    return num;
  }

  T denominator() const {
    return denom;
  }

  rational<T> operator+(const rational<T>& that) const {
    T n = numerator() * that.denominator() + that.numerator() * denominator();
    T d = denominator() * that.denominator();
    return rational<T>(n,d);
  }

  rational<T> operator-() const{
    return rational<T>( - numerator(), denominator());
  }

  rational<T> operator-(const rational<T>& that) const{
    return *this + (- that);
  }

  rational<T> operator*(const rational<T>& that) const {
    return rational<T>(numerator()   * that.numerator(),
		       denominator() * that.denominator());
  }

  rational<T> operator/(const rational<T>& that) const {
    return rational<T>(numerator()   * that.denominator(),
		       denominator() * that.numerator());
  }

private:
  T gcd(T a, T b){
    if(b == 0){
      return a;
    }else{
      return gcd(b, a % b);
    }
  }
};

template <typename T>
std::ostream& operator<< (std::ostream& out, const rational<T>& r ){
  if(r.denominator() < 0) {
    return out << "-" << r.numerator() << "/" << (- r.denominator());
  }else{
    return out << r.numerator() << "/" << r.denominator();
  }
}

int main(int argc, char *argv[])
{
  using namespace std;
  rational<int> r1(1,2);
  rational<int> r2(2,3);

  cout << (r1 + r2) << endl;
  cout << (r1 - r2) << endl;
  cout << (r1 * r2) << endl;
  cout << (r1 / r2) << endl;

  return 0;
}