This month, I am providing a handy method for whomever needs to transform a decimal value in a fraction representation. I have been required to do this in the past few months on a report. For example 1.25 needed to be read as 1 1/4.
This month demo code
The code of this month demo is provided both in VB and C#. The solution was created using Visual Studio 2012 but the same code can be reused in older version as well.
The UI
You can’t really have a simpler user interface. Two textboxes to let the user (you) provide the decimal value and the denominator and a listbox to show the results.
Figure 1: The demo application in action
Notice that when you run the application, the listbox will automatically be populated with a couple of values I used for testing.
The MakeFraction method
The real value of this article is in that method. Don’t look for something else, it is all in there!
According to the second argument of the method (pLargestDenominator), the GCD (Greatest Common Denominator is found) and the fraction is created based on it (more about this argument here below).
The method reads like this:
Private Function MakeFraction(ByVal pDecimalNumber As Decimal, Optional ByVal pLargestDenominator As Integer = 64) As String Dim intGCD As Integer Dim intTopNumber As Integer Dim intRemainder As Integer Dim intWholeNumber As Integer Dim intNumerator As Integer Dim intDenominator As Integer Dim blnIsNegative As Boolean = (pDecimalNumber < 0) pDecimalNumber = Math.Abs(pDecimalNumber) intWholeNumber = Convert.ToInt32(Fix(pDecimalNumber)) intDenominator = pLargestDenominator If (pDecimalNumber - intWholeNumber) = 0 Then Return If(blnIsNegative, "-", "") + intWholeNumber.ToString() Else intNumerator = Convert.ToInt32(intDenominator * Math.Abs(pDecimalNumber - intWholeNumber)) If intNumerator <> 0 Then intGCD = pLargestDenominator intTopNumber = intNumerator Do intRemainder = (intGCD Mod intTopNumber) intGCD = intTopNumber intTopNumber = intRemainder Loop Until intRemainder = 0 intNumerator = intNumerator \ intGCD intDenominator = intDenominator \ intGCD If intDenominator = 1 Then Return If(blnIsNegative, "-", "") + (intWholeNumber + 1).ToString() Else Return If(blnIsNegative, "-", "") + intWholeNumber.ToString() + " " + intNumerator.ToString() + "/" + intDenominator.ToString() End If End If End If End Function
The Largest Denominator argument
You need to be aware of the kind of data that you are handling.
For example, if you are dealing with weight in pounds, you better set the Largest Denominator parameter to 16 (since there are 16 ounces in a pound). If you are dealing with dollar, this parameter would make sense with a value of 100. If you are dealing with pizzas that you cut in 8 slices, guess what the perfect value would be? I’ll give you a hint, a value between 7 and 9!
Setting this argument to a value that doesn’t match the domain of values will return you a value (the closest one) based on the provided denominator but it won’t be THE exact fraction.
Interesting conversion facts
While I was converting the solution from my original VB code to C#, I found 2 interesting conversion tips.
The first one is about the well know VB Fix method. This method returns the integer portion of a number. It doesn’t round the number and it also behaves correctly with negative numbers. This method is part of the Microsoft Visual Basic component because it comes from the VB pre .Net era (it is legacy). While C# developers can add a reference to that component without a problem and (ab)use it, there is another way. Apparently, the simple fact of casting the number to an integer is enough (i.e.: (int)myDecimalValue).
The second conversion tip is about the \ operator which is only available to VB programmers. It divides two numbers and returns an integer result whatever data types the two number have. In C#, you can use the regular / operator and as long as both numbers are already integers, the returned result will also be an integer.
Conclusion
If you know what kind of data you are dealing with and want to see fractions instead of decimal values, this little method is for you.