--- /dev/null
+/*\r
+ * Karinto Library Project\r
+ *\r
+ * This software is distributed under a zlib-style license.\r
+ * See license.txt for more information.\r
+ */\r
+\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Text;\r
+using System.Text.RegularExpressions;\r
+\r
+namespace Karinto.Numeric\r
+{\r
+ public class Rational : Rational<decimal>\r
+ {\r
+ public Rational()\r
+ : base()\r
+ { \r
+ }\r
+\r
+ public Rational(decimal number)\r
+ : base(number)\r
+ {\r
+ }\r
+\r
+ public Rational(decimal numerator, decimal denominator)\r
+ : base(numerator, denominator)\r
+ {\r
+ }\r
+\r
+ public static implicit operator int(Rational rational)\r
+ {\r
+ return (int)(rational.Numerator / rational.Denominator);\r
+ }\r
+ }\r
+\r
+ public class Rational<T> where T : IComparable, new()\r
+ {\r
+ #region fields\r
+ private static readonly Regex splitter =\r
+ new Regex(@"(?:(.+)/\s*)?([^/\s]+)\s*$");\r
+\r
+ private T num;\r
+ private T den;\r
+\r
+ #endregion\r
+\r
+ #region constructor\r
+ public Rational()\r
+ : this(Operator<T>.Zero, Operator<T>.One)\r
+ { \r
+ }\r
+\r
+ public Rational(T number)\r
+ : this(number, Operator<T>.One)\r
+ {\r
+ }\r
+\r
+ public Rational(T numerator, T denominator)\r
+ {\r
+ Numerator = numerator;\r
+ Denominator = denominator;\r
+ }\r
+\r
+ static Rational()\r
+ {\r
+ \r
+ }\r
+ #endregion\r
+\r
+ #region operators\r
+\r
+ public static implicit operator Rational(Rational<T> rational)\r
+ {\r
+ decimal n = Convert.ToDecimal(rational.num);\r
+ decimal d = Convert.ToDecimal(rational.den);\r
+ return new Rational(n, d);\r
+ }\r
+\r
+ public static implicit operator int(Rational<T> rational)\r
+ {\r
+ return (int)((Rational)rational);\r
+ }\r
+\r
+ public static Rational<T> operator + \r
+ (Rational<T> left, Rational<T> right)\r
+ {\r
+ T n1 = Operator<T>.Mul(left.num, right.den);\r
+ T n2 = Operator<T>.Mul(right.num, left.den);\r
+ T n = Operator<T>.Add(n1, n2);\r
+ T d = Operator<T>.Mul(left.den, right.den);\r
+ return new Rational<T>(n, d);\r
+ }\r
+\r
+ public static Rational<T> operator -\r
+ (Rational<T> left, Rational<T> right)\r
+ {\r
+ T n1 = Operator<T>.Mul(left.num, right.den);\r
+ T n2 = Operator<T>.Mul(right.num, left.den);\r
+ T n = Operator<T>.Sub(n1, n2);\r
+ T d = Operator<T>.Mul(left.den, right.den);\r
+ return new Rational<T>(n, d);\r
+ }\r
+\r
+ public static Rational<T> operator *\r
+ (Rational<T> left, Rational<T> right)\r
+ {\r
+ T n = Operator<T>.Mul(left.num, right.num);\r
+ T d = Operator<T>.Mul(left.den, right.den);\r
+ return new Rational<T>(n, d);\r
+ }\r
+\r
+ public static Rational<T> operator /\r
+ (Rational<T> left, Rational<T> right)\r
+ {\r
+ T n = Operator<T>.Mul(left.num, right.den);\r
+ T d = Operator<T>.Mul(left.den, right.num);\r
+ return new Rational<T>(n, d);\r
+ }\r
+\r
+ #endregion\r
+\r
+ #region properties\r
+\r
+ public T Numerator\r
+ {\r
+ get\r
+ {\r
+ return num;\r
+ }\r
+ set\r
+ {\r
+ num = value;\r
+ }\r
+ }\r
+\r
+ public T Denominator\r
+ {\r
+ get\r
+ {\r
+ return den;\r
+ }\r
+ set\r
+ {\r
+ if (value.CompareTo(Operator<T>.Zero) < 0)\r
+ {\r
+ den = Operator<T>.Sub(Operator<T>.Zero, value);\r
+ num = Operator<T>.Sub(Operator<T>.Zero, num);\r
+ }\r
+ else\r
+ {\r
+ den = value;\r
+ }\r
+ }\r
+ }\r
+\r
+ #endregion\r
+\r
+ #region methods\r
+ public static Rational<T> Parse(string expression)\r
+ {\r
+ Match elements = splitter.Match(expression);\r
+ GroupCollection gc = elements.Groups;\r
+ if (gc.Count != 3)\r
+ {\r
+ throw new Exception();\r
+ }\r
+ string left = gc[1].Value;\r
+ if (left.Length == 0)\r
+ {\r
+ T n = (T)Convert.ChangeType(gc[2].Value, typeof(T));\r
+ return new Rational<T>(n);\r
+ }\r
+ T right = (T)Convert.ChangeType(gc[2].Value, typeof(T));\r
+ \r
+ return Rational<T>.Parse(left) / new Rational<T>(right);\r
+ }\r
+ #endregion\r
+\r
+ }\r
+}\r