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.