/*
 * Author: Syed Mehroz Alam
 * Email: smehrozalam@yahoo.com
 * URL: Programming Home "http://www.geocities.com/smehrozalam/" 
 * Date: 6/15/2004
 * Time: 10:54 AM
 *
 */

using System;

namespace Mehroz
{
	/// 
	/// Classes Contained:
	/// 	Application	
	/// 	Fraction
	/// 	FractionException
	/// 
	
	
	/// 
	/// The class demonstrates the Fraction class
	/// 
	public class Application
	{
		public static void Main()
		{
			try
			{
				int iNo; double dDbl;
				System.Console.Write("You can enter:\n\t an integer like \"32\" \n\tor a float like \"54.55\" \n\tor a string like \"123/567\": ");
				
				System.Console.Write("\n\nEnter value for Fraction 1: ");
				Fraction F1=new Fraction( Console.ReadLine() );

				System.Console.Write("Enter value for Fraction 2: ");
				Fraction F2=new Fraction( Console.ReadLine() );
		
				System.Console.Write("Enter any integer: ");
				iNo=System.Convert.ToInt32 ( System.Console.ReadLine() );
				System.Console.Write("Enter any floating point number: ");
				dDbl=System.Convert.ToDouble ( System.Console.ReadLine() );
		
				System.Console.WriteLine("\nF1=" + F1.ToString() );
				System.Console.WriteLine("F2=" + F2.ToString() );
				System.Console.WriteLine("Integer=" + iNo );
				System.Console.WriteLine("Double=" + dDbl );

				Console.WriteLine( "\nF1 + F2 = "+ (F1+F2).ToString() );
				Console.WriteLine( "F1 - F2 = "+ (F1-F2).ToString() );
				Console.WriteLine( "F1 * F2 = "+ (F1*F2).ToString() );
				Console.WriteLine( "F2 / F1 = "+ (F2/F1).ToString() );
				Console.WriteLine( "F1 + " + iNo + " = " + (F1+iNo).ToString() );
				Console.WriteLine( "F1 - " + iNo + " = " + (F1-iNo).ToString() );
				Console.WriteLine( "F1 * " + iNo + " = " + (F1*iNo).ToString() );
				Console.WriteLine( "F1 / " + iNo + " = " + (F1/iNo).ToString() );
				Console.WriteLine( "F1 + " + dDbl + " = " + (F1+dDbl).ToString() );
				Console.WriteLine( "F1 - " + dDbl + " = " + (F1-dDbl).ToString() );
				Console.WriteLine( "F1 * " + dDbl + " = " + (F1*dDbl).ToString() );
				Console.WriteLine("\n\nPress any key to exit");
			}	//end try
			catch (FractionException exp)
			{
				Console.WriteLine("\nInternal error: " + exp.Message);
				throw exp;
			}
			catch (Exception exp)
			{
				Console.WriteLine("\nSystem error: " + exp.Message);
			}
			Console.Read();
		}	//end main
	}//end class Application
	
	

	/// Class name: Fraction
	/// Developed by: Syed Mehroz Alam
	/// Email: smehrozalam@yahoo.com
	/// URL: Programming Home "http://www.geocities.com/smehrozalam/"
	/// Version: 2.0
	/// 
	/// What's new in version 2.0:
	/// 	*	Changed Numerator and Denominator from Int32(integer) to Int64(long) for increased range
	/// 	*	renamed ConvertToString() to (overloaded) ToString()
	/// 	*	added the capability of detecting/raising overflow exceptions
	/// 	*	Fixed the bug that very small numbers e.g. 0.00000001 could not be converted to fraction
	/// 	*	Other minor bugs fixed
	/// 
	/// What's new in version 2.1
	/// 	*	overloaded user-defined conversions to/from Fractions
	/// 	
	/// 
	/// Properties:
	/// 	Numerator: Set/Get value for Numerator
	/// 	Denominator:  Set/Get value for Numerator
	/// 	Value:  Set an integer value for the fraction
	/// 
	/// Constructors:
	/// 	no arguments:	initializes fraction as 0/1
	/// 	(Numerator, Denominator): initializes fraction with the given numerator and denominator values
	/// 	(integer):	initializes fraction with the given integer value
	/// 	(long):	initializes fraction with the given long value
	/// 	(double):	initializes fraction with the given double value
	/// 	(string):	initializes fraction with the given string value
	/// 				the string can be an in the form of and integer, double or fraction.
	/// 				e.g it can be like "123" or "123.321" or "123/456"
	/// 
	/// Public Methods (Description is given with respective methods' definitions)
	/// 	(override) string ToString(Fraction)
	/// 	Fraction ToFraction(string)
	/// 	Fraction ToFraction(double)
	/// 	double ToDouble(Fraction)
	/// 	Fraction Duplicate()
	/// 	Fraction Inverse(integer)
	/// 	Fraction Inverse(Fraction)
	/// 	ReduceFraction(Fraction)
	/// 	Equals(object)
	/// 	GetHashCode()
	/// 
	///	Private Methods (Description is given with respective methods' definitions)
	/// 	Initialize(Numerator, Denominator)
	/// 	Fraction Negate(Fraction)
	/// 	Fraction Add(Fraction1, Fraction2)
	/// 
	/// Overloaded Operators (overloaded for Fractions, Integers and Doubles)
	/// 	Unary: -
	/// 	Binary: +,-,*,/ 
	/// 	Relational and Logical Operators: ==,!=,<,>,<=,>=
	/// 
	/// Overloaded user-defined conversions
	/// 	Implicit:	From double/long/string to Fraction
	/// 	Explicit:	From Fraction to double/string
	/// 
	public class Fraction
	{
		/// 
		/// Class attributes/members
		/// 
		long m_iNumerator;
		long m_iDenominator;
		
		/// 
		/// Constructors
		/// 
		public Fraction()
		{
			Initialize(0,1);
		}
	
		public Fraction(long iWholeNumber)
		{
			Initialize(iWholeNumber, 1);
		}
	
		public Fraction(double dDecimalValue)
		{
			Fraction temp=ToFraction(dDecimalValue);
			Initialize(temp.Numerator, temp.Denominator);
		}
		
		public Fraction(string strValue)
		{
			Fraction temp=ToFraction(strValue);
			Initialize(temp.Numerator, temp.Denominator);
		}
		
		public Fraction(long iNumerator, long iDenominator)
		{
			Initialize(iNumerator, iDenominator);
		}
		
		/// 
		/// Internal function for constructors
		/// 
		private void Initialize(long iNumerator, long iDenominator)
		{
			Numerator=iNumerator;
			Denominator=iDenominator;
			ReduceFraction(this);
		}
	
		/// 
		/// Properites
		/// 
		public long Denominator
		{
			get
			{	return m_iDenominator;	}
			set
			{
				if (value!=0)
					m_iDenominator=value;
				else
					throw new FractionException("Denominator cannot be assigned a ZERO Value");
			}
		}
	
		public long Numerator
		{
			get	
			{	return m_iNumerator;	}
			set
			{	m_iNumerator=value;	}
		}
	
		public long Value
		{
			set
			{	m_iNumerator=value;
				m_iDenominator=1;	}
		}
	
		/// 
		/// The function returns the current Fraction object as double
		/// 
		public double ToDouble()
		{
			return ( (double)this.Numerator/this.Denominator );
		}

		/// 
		/// The function returns the current Fraction object as a string
		/// 
		public override string ToString()
		{
			string str;
			if ( this.Denominator==1 )
				str=this.Numerator.ToString();
			else
				str=this.Numerator + "/" + this.Denominator;
			return str;
		}
		/// 
		/// The function takes an string as an argument and returns its corresponding reduced fraction
		/// the string can be an in the form of and integer, double or fraction.
		/// e.g it can be like "123" or "123.321" or "123/456"
		/// 
		public static Fraction ToFraction(string strValue)
		{
			int i;
			for (i=0;i
		/// The function takes a floating point number as an argument 
		/// and returns its corresponding reduced fraction
		/// 
		public static Fraction ToFraction(double dValue)
		{
			try
			{
				checked
				{
					Fraction frac;
					if (dValue%1==0)	// if whole number
					{
						frac=new Fraction( (long) dValue );
					}
					else
					{
						double dTemp=dValue;
						long iMultiple=1;
						string strTemp=dValue.ToString();
						while ( strTemp.IndexOf("E")>0 )	// if in the form like 12E-9
						{
							dTemp*=10;
							iMultiple*=10;
							strTemp=dTemp.ToString();
						}
						int i=0;
						while ( strTemp[i]!='.' )
							i++;
						int iDigitsAfterDecimal=strTemp.Length-i-1;
						while ( iDigitsAfterDecimal>0  )
						{
							dTemp*=10;
							iMultiple*=10;
							iDigitsAfterDecimal--;
						}
						frac=new Fraction( (int)Math.Round(dTemp) , iMultiple );
					}
					return frac;
				}
			}
			catch(OverflowException)
			{
				throw new FractionException("Conversion not possible due to overflow");
			}
			catch(Exception)
			{
				throw new FractionException("Conversion not possible");
			}
		}

		/// 
		/// The function replicates current Fraction object
		/// 
		public Fraction Duplicate()
		{
			Fraction frac=new Fraction();
			frac.Numerator=Numerator;
			frac.Denominator=Denominator;
			return frac;
		}

		/// 
		/// The function returns the inverse of a Fraction object
		/// 
		public static Fraction Inverse(Fraction frac1)
		{
			if (frac1.Numerator==0)
				throw new FractionException("Operation not possible (Denominator cannot be assigned a ZERO Value)");
	
			long iNumerator=frac1.Denominator;
			long iDenominator=frac1.Numerator;
			return ( new Fraction(iNumerator, iDenominator));
		}	
	

		/// 
		/// Operators for the Fraction object
		/// includes -(unary), and binary opertors such as +,-,*,/
		/// also includes relational and logical operators such as ==,!=,<,>,<=,>=
		/// 
		public static Fraction operator -(Fraction frac1)
		{	return ( Negate(frac1) );	}
	                              
		public static Fraction operator +(Fraction frac1, Fraction frac2)
		{	return ( Add(frac1 , frac2) );	}
	
		public static Fraction operator +(int iNo, Fraction frac1)
		{	return ( Add(frac1 , new Fraction(iNo) ) );	}
	
		public static Fraction operator +(Fraction frac1, int iNo)
		{	return ( Add(frac1 , new Fraction(iNo) ) );	}

		public static Fraction operator +(double dbl, Fraction frac1)
		{	return ( Add(frac1 , Fraction.ToFraction(dbl) ) );	}
	
		public static Fraction operator +(Fraction frac1, double dbl)
		{	return ( Add(frac1 , Fraction.ToFraction(dbl) ) );	}
	
		public static Fraction operator -(Fraction frac1, Fraction frac2)
		{	return ( Add(frac1 , -frac2) );	}
	
		public static Fraction operator -(int iNo, Fraction frac1)
		{	return ( Add(-frac1 , new Fraction(iNo) ) );	}
	
		public static Fraction operator -(Fraction frac1, int iNo)
		{	return ( Add(frac1 , -(new Fraction(iNo)) ) );	}

		public static Fraction operator -(double dbl, Fraction frac1)
		{	return ( Add(-frac1 , Fraction.ToFraction(dbl) ) );	}
	
		public static Fraction operator -(Fraction frac1, double dbl)
		{	return ( Add(frac1 , -Fraction.ToFraction(dbl) ) );	}
	
		public static Fraction operator *(Fraction frac1, Fraction frac2)
		{	return ( Multiply(frac1 , frac2) );	}
	
		public static Fraction operator *(int iNo, Fraction frac1)
		{	return ( Multiply(frac1 , new Fraction(iNo) ) );	}
	
		public static Fraction operator *(Fraction frac1, int iNo)
		{	return ( Multiply(frac1 , new Fraction(iNo) ) );	}
	
		public static Fraction operator *(double dbl, Fraction frac1)
		{	return ( Multiply(frac1 , Fraction.ToFraction(dbl) ) );	}
	
		public static Fraction operator *(Fraction frac1, double dbl)
		{	return ( Multiply(frac1 , Fraction.ToFraction(dbl) ) );	}
	
		public static Fraction operator /(Fraction frac1, Fraction frac2)
		{	return ( Multiply( frac1 , Inverse(frac2) ) );	}
	
		public static Fraction operator /(int iNo, Fraction frac1)
		{	return ( Multiply( Inverse(frac1) , new Fraction(iNo) ) );	}
	
		public static Fraction operator /(Fraction frac1, int iNo)
		{	return ( Multiply( frac1 , Inverse(new Fraction(iNo)) ) );	}
	
		public static Fraction operator /(double dbl, Fraction frac1)
		{	return ( Multiply( Inverse(frac1) , Fraction.ToFraction(dbl) ) );	}
	
		public static Fraction operator /(Fraction frac1, double dbl)
		{	return ( Multiply( frac1 , Fraction.Inverse( Fraction.ToFraction(dbl) ) ) );	}

		public static bool operator ==(Fraction frac1, Fraction frac2)
		{	return frac1.Equals(frac2);		}

		public static bool operator !=(Fraction frac1, Fraction frac2)
		{	return ( !frac1.Equals(frac2) );	}

		public static bool operator ==(Fraction frac1, int iNo)
		{	return frac1.Equals( new Fraction(iNo));	}

		public static bool operator !=(Fraction frac1, int iNo)
		{	return ( !frac1.Equals( new Fraction(iNo)) );	}
		
		public static bool operator ==(Fraction frac1, double dbl)
		{	return frac1.Equals( new Fraction(dbl));	}

		public static bool operator !=(Fraction frac1, double dbl)
		{	return ( !frac1.Equals( new Fraction(dbl)) );	}
		
		public static bool operator<(Fraction frac1, Fraction frac2)
		{	return frac1.Numerator * frac2.Denominator < frac2.Numerator * frac1.Denominator;	}

		public static bool operator>(Fraction frac1, Fraction frac2)
		{	return frac1.Numerator * frac2.Denominator > frac2.Numerator * frac1.Denominator;	}

		public static bool operator<=(Fraction frac1, Fraction frac2)
		{	return frac1.Numerator * frac2.Denominator <= frac2.Numerator * frac1.Denominator;	}
		
		public static bool operator>=(Fraction frac1, Fraction frac2)
		{	return frac1.Numerator * frac2.Denominator >= frac2.Numerator * frac1.Denominator;	}
		
		
		/// 
		/// overloaed user defined conversions: from numeric data types to Fractions
		/// 
		public static implicit operator Fraction(long lNo)
		{	return new Fraction(lNo);	}
		public static implicit operator Fraction(double dNo)
		{	return new Fraction(dNo);	}
		public static implicit operator Fraction(string strNo)
		{	return new Fraction(strNo);	}

		/// 
		/// overloaed user defined conversions: from fractions to double and string
		/// 
		public static explicit operator double(Fraction frac)
		{	return frac.ToDouble();	}

		public static implicit operator string(Fraction frac)
		{	return frac.ToString();	}
		
		/// 
		/// checks whether two fractions are equal
		/// 
		public override bool Equals(object obj)
		{
			Fraction frac=(Fraction)obj;
			return ( Numerator==frac.Numerator && Denominator==frac.Denominator);
		}
		
		/// 
		/// returns a hash code for this fraction
		/// 
   		public override int GetHashCode()
   		{
			return ( Convert.ToInt32((Numerator ^ Denominator) & 0xFFFFFFFF) ) ;
		}

		/// 
		/// internal function for negation
		/// 
		private static Fraction Negate(Fraction frac1)
		{
			long iNumerator=-frac1.Numerator;
			long iDenominator=frac1.Denominator;
			return ( new Fraction(iNumerator, iDenominator) );

		}	

		/// 
		/// internal functions for binary operations
		/// 
		private static Fraction Add(Fraction frac1, Fraction frac2)
		{
			try
			{
				checked
				{
					long iNumerator=frac1.Numerator*frac2.Denominator + frac2.Numerator*frac1.Denominator;
					long iDenominator=frac1.Denominator*frac2.Denominator;
					return ( new Fraction(iNumerator, iDenominator) );
				}
			}
			catch(OverflowException)
			{
				throw new FractionException("Overflow occurred while performing arithemetic operation");
			}
			catch(Exception)
			{
				throw new FractionException("An error occurred while performing arithemetic operation");
			}
		}
	
		private static Fraction Multiply(Fraction frac1, Fraction frac2)
		{
			try
			{
				checked
				{
					long iNumerator=frac1.Numerator*frac2.Numerator;
					long iDenominator=frac1.Denominator*frac2.Denominator;
					return ( new Fraction(iNumerator, iDenominator) );
				}
			}
			catch(OverflowException)
			{
				throw new FractionException("Overflow occurred while performing arithemetic operation");
			}
			catch(Exception)
			{
				throw new FractionException("An error occurred while performing arithemetic operation");
			}
		}

		/// 
		/// The function returns GCD of two numbers (used for reducing a Fraction)
		/// 
		private static long GCD(long iNo1, long iNo2)
		{
			// take absolute values
			if (iNo1 < 0) iNo1 = -iNo1;
			if (iNo2 < 0) iNo2 = -iNo2;
			
			do
			{
				if (iNo1 < iNo2)
				{
					long tmp = iNo1;  // swap the two operands
					iNo1 = iNo2;
					iNo2 = tmp;
				}
				iNo1 = iNo1 % iNo2;
			} while (iNo1 != 0);
			return iNo2;
		}
	
		/// 
		/// The function reduces(simplifies) a Fraction object by dividing both its numerator 
		/// and denominator by their GCD
		/// 
		public static void ReduceFraction(Fraction frac)
		{
			try
			{
				if (frac.Numerator==0)
				{
					frac.Denominator=1;
					return;
				}
				
				long iGCD=GCD(frac.Numerator, frac.Denominator);
				frac.Numerator/=iGCD;
				frac.Denominator/=iGCD;
				
				if ( frac.Denominator<0 )	// if -ve sign in denominator
				{
					//pass -ve sign to numerator
					frac.Numerator*=-1;
					frac.Denominator*=-1;	
				}
			} // end try
			catch(Exception exp)
			{
				throw new FractionException("Cannot reduce Fraction: " + exp.Message);
			}
		}
			
	}	//end class Fraction


	/// 
	/// Exception class for Fraction, derived from System.Exception
	/// 
	public class FractionException : Exception
	{
		public FractionException() : base()
		{}
	
		public FractionException(string Message) : base(Message)
		{}
		
		public FractionException(string Message, Exception InnerException) : base(Message, InnerException)
		{}
	}	//end class FractionException
	

}	//end namespace Mehroz

    Source: geocities.com/smehrozalam/source

               ( geocities.com/smehrozalam)