I’m not really sure why Microsoft have never bother with implementing a Fraction primitive in .NET. I’m sure there are plenty of uses as fraction allow to preserve the maximum possible precision.I have therefore decided to create my own implementation.
My implementation automatically simplifies the fraction, so if you were to create new Function(6, 3) that would be simplified to 2. The Fraction struct implements all the arithmetic operators on itself and on Int64, float, double and decimal.
Internally the Fraction is represented as two Int64: Numerator and Denominator and is always simplified upon initialization. I initially intended to have it as an option, however, following profiling, the cost of simplification is not that great and the benefits outweigh the performance drawbacks.
Fraction has an explicit conversion to Int64 (although that is bound to lose precision), float, double and decimal. It supports comparison with Int64, float, double and decimal and even supports ++ and — operations.
So far I have provided more or less complete implementation with plenty of Unit Test. Now the hard work of optimizing the performance begins!
Design of Fractions
Fraction is implemented as a struct (pretty obvious choice). It takes a numerator as the first argument and denominator, it then tries to simplify the fraction using the Euclidean algorithm, so if you were to specify 333/111 it would become 3.
The implementation supports all arithmetic operations with long, float, double and decimal and can also be converted to those type by either calling the corresponding methods or using the explicit cast.
You can also create a function from either a long, float, double or decimal. Conversion from a long is quite trivial however conversion from a float, double or a decimal goes through a while loop and multiplies the floating point number until it has no decimal places. This method is relatively slow and therefore is not recommended.
Apart from that, the Fraction behaves like a first class citizen: you can compare a Fraction to any other number, divide, multiply, add, subtract, compare, increment decrement etc.
var oneThird = Fraction(1, 3);
var reciprocal = oneThird.Reciprocal();
Console.WriteLine(oneThird * reciprocal) : "1"
Console.WriteLine(++oneThird) : "4/3" - just like with an integer ++ adds 1
Console.WriteLine(oneThird * oneThird) : "1/9"
Please feel free to contribute to the codebase if you feel like it