OSDN Git Service

四則演算を一般化したOperatorクラスの追加,有理数クラスの追加
[karinto/karinto.git] / Karinto / Numeric / Rational.cs
diff --git a/Karinto/Numeric/Rational.cs b/Karinto/Numeric/Rational.cs
new file mode 100755 (executable)
index 0000000..a1751bc
--- /dev/null
@@ -0,0 +1,182 @@
+/*\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