Created
December 13, 2010 18:49
-
-
Save maraigue/739403 to your computer and use it in GitHub Desktop.
A simple rational number (or fraction) class in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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