Skip to content

Instantly share code, notes, and snippets.

@maraigue
Created December 13, 2010 18:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maraigue/739403 to your computer and use it in GitHub Desktop.
Save maraigue/739403 to your computer and use it in GitHub Desktop.
A simple rational number (or fraction) class in C#
namespace SimpleRational
{
public class Rational
{
private int _numerator = 0;
private int _denominator = 1;
// コンストラクタ
public Rational(int int_value)
{
set(int_value, 1);
}
public Rational(int new_numerator, int new_denominator)
{
set(new_numerator, new_denominator);
}
// アクセサ
public void set(int new_numerator, int new_denominator)
{
if (new_denominator == 0)
{
throw new ArithmeticException("Denominator must not be 0");
}
_numerator = new_numerator;
_denominator = new_denominator;
}
public int numerator()
{
return _numerator;
}
public void numerator(int new_numerator)
{
_numerator = new_numerator;
}
public int denominator()
{
return _denominator;
}
public void denominator(int new_denominator)
{
if (new_denominator == 0)
{
throw new ArithmeticException("Denominator must not be 0");
}
_denominator = new_denominator;
}
// ---------- 補助関数 ----------
// 最大公約数
public static int gcd(int v1, int v2)
{
int tmp;
// どちらかが0だったら即座に終了
if (v1 == 0 || v2 == 0) return 0;
// 正の値にしておく
if (v1 < 0) v1 = -v1;
if (v2 < 0) v2 = -v2;
// v1の方を大きくしておく
if (v2 > v1)
{
tmp = v1; v1 = v2; v2 = tmp;
}
for (; ; )
{
tmp = v1 % v2;
if (tmp == 0) return v2;
v1 = v2; v2 = tmp;
}
}
// 通分する
private void _fix_denominator(Rational other)
{
int tmp = _denominator;
_numerator *= other._denominator;
_denominator *= other._denominator;
other._numerator *= tmp;
other._denominator *= tmp;
}
// 正規化
// ●分子・分母を約分する
// ●負の符号が分母についている場合、分子にのみつけるようにする
// ●値が0である場合は「0/1」にする
private void _regularize()
{
int divisor = Math.Sign(_denominator) * gcd(_numerator, _denominator);
if (divisor == 0)
{
// 分子が0の場合
_numerator = 0;
_denominator = 1;
}
else
{
_numerator /= divisor;
_denominator /= divisor;
}
}
// ---------- 比較 ----------
public static bool operator ==(Rational r1, Rational r2)
{
r1._regularize();
r2._regularize();
return (r1._numerator == r2._numerator && r1._denominator == r2._denominator);
}
public static bool operator !=(Rational r1, Rational r2)
{
return (r1 != r2);
}
public static bool operator <(Rational r1, Rational r2)
{
r1._fix_denominator(r2);
return (r1.numerator() < r2.numerator());
}
public static bool operator >(Rational r1, Rational r2)
{
return (r2 < r1);
}
// 以下、他の関数やクラスに使ってもらう際の補助関数
public override bool Equals(object obj)
{
if (obj.GetType() == this.GetType())
{
return (this == (Rational)obj);
}
return false;
}
public override int GetHashCode()
{
return (_numerator | (_denominator << 16));
}
// ---------- 型変換 ----------
public static explicit operator double(Rational r)
{
return (double)r._numerator / (double)r._denominator;
}
public static explicit operator float(Rational r)
{
return (float)r._numerator / (float)r._denominator;
}
// ---------- 加減乗除 ----------
public static Rational operator +(Rational r) // 単項演算子
{
// 単に自分のコピーを作ればよい
return new Rational(r._numerator, r._denominator);
}
public static Rational operator -(Rational r) // 単項演算子
{
return new Rational(-r._numerator, r._denominator);
}
public static Rational operator +(Rational r1, Rational r2) // 二項演算子
{
r1._fix_denominator(r2);
return new Rational(r1._numerator + r2._numerator, r1._denominator);
}
public static Rational operator -(Rational r1, Rational r2) // 二項演算子
{
r1._fix_denominator(r2);
return new Rational(r1._numerator - r2._numerator, r1._denominator);
}
public static Rational operator *(Rational r1, Rational r2)
{
return new Rational(r1._numerator * r2._numerator, r1._denominator * r2._denominator);
}
public static Rational operator /(Rational r1, Rational r2)
{
if (r2._numerator == 0)
{
throw new DivideByZeroException();
}
return new Rational(r1._numerator * r2._denominator, r1._denominator * r2._numerator);
}
// ユーティリティ
public override string ToString()
{
_regularize();
if (_denominator == 1) return _numerator.ToString();
return string.Format("({0}/{1})", _numerator, _denominator);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment