Many students (like me) get confronted with this Fraction class Tasks if they are learning C#.
I want to provide one solution (out of a million others) to understand how things are working.
There is still room for improvement (e.g. Exceptions etc.) but I think it´s easier to get a first impression for the functionalities if I leave it beside. For the same reasons I reduced the comments in Fraction class.
If you want me to add theese, I will do so.
I thought tapping through it in Debug Modus will show everything you need to know.
If you have any suggestions to make it better, I´d appreciate that!
Thanks to Koopakiller, I changed the method based approach to overloaded operators.
I found this link to MSDN useful to learn how overloaded operator work.
https://msdn.microsoft.com/de-de/library/6fbs5e2h.aspx
For compatibilitie reasons the class should contain a method based solution too.
You´ll find an example for the IFormattable intergration too. The web sources are pasted as a comment in the specific regions.
Here is some sample data for your Programm Main():
Fraction a = new Fraction(1, 2);
Fraction b = new Fraction(1, 4);
Fraction c = new Fraction(7, 2);
Fraction d = new Fraction(1, 2);
Fraction x = new Fraction(0.25);
Fraction y = new Fraction(0.255845121);
Console.WriteLine("Addition");
Console.WriteLine("{0} + {1} = {2}", a, b, a + b);
Console.WriteLine("{0} + 2 = {1}", a, a + 2);
Console.WriteLine("{0} + 0,25 = {1}", a, a + 0.25);
Console.WriteLine();
Console.WriteLine("Substraction / Subtrahieren");
Console.WriteLine("{0} - {1} = {2}", a, b, a - b);
Console.WriteLine("{0} - 2 = {1}", c, c - 2);
Console.WriteLine("{0} - 0,25 = {1}", a, a - 0.25);
Console.WriteLine();
Console.WriteLine("Multiplication / Multiplizieren");
Console.WriteLine("{0} * {1} = {2}", a, b, a * b);
Console.WriteLine("{0} * 2 = {1}", c, c * 2);
Console.WriteLine("{0} * 0,25 = {1}", a, a * 0.25);
Console.WriteLine();
Console.WriteLine("Divison / Dividieren");
Console.WriteLine("{0} / {1} = {2}", a, b, a / b);
Console.WriteLine("{0} / 2 = {1}", a, a / 2);
Console.WriteLine("{0} / 0,25 = {1}", a, a / 0.25);
Console.WriteLine();
Console.WriteLine(c +" after Reciprocal() = " + c.Reciprocal());
Console.WriteLine();
Console.WriteLine("Evaluate / Evaluieren");
Console.WriteLine(x + " as decimal number = " + x.Evaluate());
Console.WriteLine(y + " with 5 decimal places = " + y.Evaluate(5));
Console.WriteLine();
Console.WriteLine("ToString() with IFromattable");
Console.WriteLine("ToString() for "+ c + " without parameters, displayed as a Fraction > " + c.ToString());
Console.WriteLine("ToString() for " + c + " with parameter F, displayed as a Fraction > " + c.ToString("F"));
Console.WriteLine("ToString() for " + c + " with parameter M, displayed as a Mixed Numbers > " + c.ToString("M"));
Console.ReadKey();
using System;
using System.Globalization;
namespace Fraction
{
class Fraction : IFormattable
{
// numerator = Zähler / denominator = Nenner
public long numerator { get; private set;}
public long denominator { get; private set; }
private int exponent { get; set; }
public Fraction(long numerator)
{
this.numerator = numerator;
this.denominator = 1;
}
public Fraction(double adouble)
{
this.exponent = (Decimal.GetBits((decimal)adouble)[3] & 0x0ff0000) >> 0x10;
this.denominator = (long)System.Math.Pow(10, exponent);
this.numerator = (long)(adouble * denominator);
Reduce();
}
public Fraction(long numerator = 0, long denominator = 1)
{
this.numerator = numerator;
this.denominator = denominator;
Reduce();
}
public Fraction(Fraction aFraction)
{
numerator = aFraction.numerator;
denominator = aFraction.denominator;
}
// get Greatest Common Divisor(Greatest Common Divisor)
static public long GetGCD(long a, long b)
{
if (a == b || b == 0)
{
return a;
}
else return GetGCD(b, a % b);
}
protected void Reduce()
{
if (denominator == 0)
{
numerator = 0;
denominator = 1;
}
if (denominator < 0)
{
denominator *= -1;
numerator *= -1;
}
long gcd = GetGCD(numerator, denominator);
if (gcd != 0)
{
numerator /= gcd;
denominator /= gcd;
}
}
#region Calculating Methods Add / Substract / Multiply / Divide
#region Method Add
public Fraction Add(Fraction f1)
{
return new Fraction(this.numerator * f1.denominator + this.denominator * f1.numerator, this.denominator * f1.denominator);
}
public Fraction Add(int i)
{
return this.Add(new Fraction(i));
}
public Fraction Add(double i)
{
return this.Add(new Fraction(i));
}
#endregion
#region Method Substract
public Fraction Substract(Fraction f1)
{
return new Fraction(this.numerator * f1.denominator - this.denominator * f1.numerator, this.denominator * f1.denominator);
}
public Fraction Substract(int i)
{
return this.Substract(new Fraction(i));
}
public Fraction Substract(double i)
{
return this.Substract(new Fraction(i));
}
#endregion
#region Method Multiply
public Fraction Multiply(Fraction f1)
{
return new Fraction(this.numerator * f1.numerator, this.denominator * f1.denominator);
}
public Fraction Multiply(int i)
{
return this.Multiply(new Fraction(i));
}
public Fraction Multiply(double i)
{
return this.Multiply(new Fraction(i));
}
#endregion
#region Method Divide
public Fraction Divide(Fraction f1)
{
return this.Multiply(f1.Reciprocal());
}
public Fraction Divide(int i)
{
return this.Divide(new Fraction(i));
}
public Fraction Divide(double i)
{
return this.Divide(new Fraction(i));
}
#endregion
#endregion
#region overloaded operators
// Readmore about overloading operators @ https://msdn.microsoft.com/de-de/library/6fbs5e2h.aspx
#region operator +
public static Fraction operator +(Fraction f1, Fraction f2)
{
return new Fraction((f1.numerator * f2.denominator + f1.denominator * f2.numerator), f1.denominator * f2.denominator);
}
public static Fraction operator +(Fraction f1, int i)
{
return f1 + new Fraction(i);
}
public static Fraction operator +(int i, Fraction f1)
{
return f1 + i;
}
public static Fraction operator +(Fraction f1, double i)
{
return f1 + new Fraction(i);
}
public static Fraction operator +(double i, Fraction f1)
{
return f1 + new Fraction(i);
}
#endregion
#region operator -
public static Fraction operator -(Fraction f1, Fraction f2)
{
return new Fraction(((f1.numerator * f2.denominator) - (f1.denominator * f2.numerator)), f1.denominator * f2.denominator);
}
public static Fraction operator -(Fraction f1, int i)
{
return f1 - new Fraction(i);
}
public static Fraction operator -(int i, Fraction f1)
{
return f1 - new Fraction(i);
}
public static Fraction operator -(Fraction f1, double i)
{
return f1 - new Fraction(i);
}
public static Fraction operator -(double i, Fraction f1)
{
return f1 - new Fraction(i);
}
#endregion
#region operator *
public static Fraction operator *(Fraction f1, Fraction f2)
{
return new Fraction(f1.numerator * f2.numerator, f1.denominator * f2.denominator);
}
public static Fraction operator *(Fraction f1, int i)
{
return new Fraction(f1 * new Fraction(i));
}
public static Fraction operator *(int i, Fraction f1)
{
return new Fraction(f1 * new Fraction(i));
}
public static Fraction operator *(Fraction f1, double i)
{
return f1 * new Fraction(i);
}
public static Fraction operator *(double i, Fraction f1)
{
return f1 * new Fraction(i);
}
#endregion
#region operator /
public static Fraction operator /(Fraction f1, Fraction f2)
{
return new Fraction(f1 * f2.Reciprocal());
}
public static Fraction operator /(Fraction f1, int i)
{
return new Fraction(f1 / new Fraction(i));
}
public static Fraction operator /(int i, Fraction f1)
{
return new Fraction(f1 / new Fraction(i));
}
public static Fraction operator /(Fraction f1, double i)
{
return f1 / new Fraction(i);
}
public static Fraction operator /(double i, Fraction f1)
{
return f1 / new Fraction(i);
}
#endregion
#endregion
public Fraction Reciprocal()
{
return new Fraction(this.denominator, this.numerator);
}
public double Evaluate()
{
return (double)this.numerator / this.denominator;
}
public double Evaluate(int lenght)
{
if (lenght <= exponent)
return Math.Round((double)this.numerator / this.denominator, lenght);
return Math.Round((double)this.numerator / this.denominator, lenght = exponent);
}
#region overide ToString()
// Read more about ToString with IFromattable at https://msdn.microsoft.com/de-de/library/system.iformattable%28v=vs.110%29.aspx
public override string ToString()
{
return this.ToString("F");
}
public string ToString(string format)
{
if (String.IsNullOrEmpty(format)) format = "F";
return this.ToString(format, CultureInfo.CurrentCulture);
}
public string ToString(string format, IFormatProvider formatProvider)
{
if (String.IsNullOrEmpty(format)) format = "F";
if (formatProvider == null) formatProvider = CultureInfo.CurrentCulture;
switch (format.ToUpperInvariant())
{
case "F":
if (denominator != 1)
return numerator + "/" + denominator;
return this.numerator + "";
case "M":
if (numerator / denominator != 0)
return numerator / denominator + " " + numerator % denominator + "/" + this.denominator;
return this.ToString();
default:
throw new FormatException(String.Format("The {0} format string is not supported. Please choose F (Fraction Format) or M (Mixed Numbers Fromat)", format));
}
}
#endregion
}
}