// fraction.cs by M.Inamori 7/7/03 // modified 7/23/03 using System; public class Fraction { private long a; private long b; public Fraction() { a = 0; b = 1; } public Fraction(long x) { a = x; b = 1; } public Fraction(long x, long y) { a = x; b = y; normalize(); } private static long add(long x, long y) { if((y > 0 && x > Int64.MaxValue - y) || (y < 0 && -x > Int64.MaxValue + y)) throw(new System.OverflowException()); return x + y; } private static long subtract(long x, long y) { if((y > 0 && -x > Int64.MaxValue - y) || (y < 0 && x > Int64.MaxValue + y)) throw(new System.OverflowException()); return x - y; } private static long multiple(long x, long y) { if(y == 0) return 0; long z = System.Math.Abs(Int64.MaxValue / y); long __x = System.Math.Abs(x); if(z < __x) throw(new System.OverflowException()); return x * y; } public static Fraction operator +(Fraction f) { return f.Copy(); } public static Fraction operator -(Fraction f) { Fraction f1 = new Fraction(); f1.a = -f.a; f1.b = f.b; return f1; } public static bool operator ==(Fraction f1, Fraction f2) { return f1.a == f2.a && f1.b == f2.b; } public static bool operator !=(Fraction f1, Fraction f2) { return f1.a != f2.a || f1.b != f2.b; } public static bool operator >(Fraction f1, Fraction f2) { return less(f2, f1); } public static bool operator <(Fraction f1, Fraction f2) { return less(f1, f2); } public static bool operator >=(Fraction f1, Fraction f2) { return !less(f1, f2); } public static bool operator <=(Fraction f1, Fraction f2) { return !less(f2, f1); } public static Fraction operator +(Fraction f1, Fraction f2) { return new Fraction(add(multiple(f1.a, f2.b), multiple(f1.b, f2.a)), multiple(f1.b, f2.b)); } public static Fraction operator -(Fraction f1, Fraction f2) { return new Fraction(f1.a * f2.b - f1.b * f2.a, f1.b * f2.b); } public static Fraction operator *(Fraction f1, Fraction f2) { Fraction result = new Fraction(f1.a, f2.b); long r_a = result.a; long r_b = result.b; result.a = f2.a; result.b = f1.b; result.normalize(); result.a = multiple(result.a, r_a); result.b = multiple(result.b, r_b); return result; } public static Fraction operator /(Fraction f1, Fraction f2) { Fraction result = new Fraction(f1.a, f2.a); long r_a = result.a; long r_b = result.b; result.a = f2.b; result.b = f1.b; result.normalize(); result.a = multiple(result.a, r_a); result.b = multiple(result.b, r_b); return result; } private static bool less(Fraction f1, Fraction f2) { try { return multiple(f1.a, f2.b) < multiple(f2.a, f1.b); } catch(System.OverflowException e) { if(f1 == f2) return false; long div1, div2; long f1_a, f1_b, f2_a, f2_b; f1_a = f1.a; f1_b = f1.b; f2_a = f2.a; f2_b = f2.b; while(true) { div1 = f1_a / f1_b; div2 = f2_a / f2_b; if(div1 != div2) return div1 < div2; f1_a %= f1_b; f2_a %= f2_b; div1 = f1_b / f1_a; div2 = f2_b / f2_a; if(div1 != div2) return div1 > div2; f1_b %= f1_a; f2_b %= f2_a; } } } private void normalize() { long a1, b1, a2, f; a1 = a; b1 = b; f = 1; while(true) { if((a2 = a1 % b1) == 0) { f = b1; break; } if((b1 = b1 % a1) == 0) { f = a1; break; } a1 = a2; } a /= f; b /= f; if(b < 0) { a = -a; b = -b; } } public override bool Equals(object o) { return a == ((Fraction)o).a && b == ((Fraction)o).b; } public override int GetHashCode() { return (int)((a + b) & 0x7FFFFFFF); } public Fraction Copy() { Fraction f = new Fraction(); f.a = a; f.b = b; return f; } public override string ToString() { if(b == 1) return a.ToString(); else return a + "/" + b; } }