In Focus

Calculate Fractions in VB.NET

In this brief article, we'll see a simple method to convert the decimal part of a number into its fractional representation, developing a reusable class apt to do it.

Scope

In this brief article we'll see a simple method to convert the decimal part of a number into its fractional representation, developing a reusable class to do it. To that end, we'll use Visual Basic .NET.

Calculate and simplify a fraction

To calculate a fraction, we must separate a number's integral part from the decimal one, to work on the latter to express it in terms of numerator and denominator. Let's take for example the number 12.65. We will first express it as 12 + 0.65, proceeding then in writing our decimal part as the most large non-simplified fraction. Since we have two decimals after the dot, the larger denominator we need is 100. So, we can express our 0.65 as 65/100. Then, using the common rules based on finding the Greatest Common Divisor (GDC), we can simplify our fraction, down to 13/20.

Finding the Greatest Common Divisor

The following is an easy snippet of code to help determine the GDC between two numbers:

  1. Private Function gcd(ByVal n1 As IntegerByVal n2 As IntegerAs Long  
  2.       Dim minimum As Long  
  3.       If n1 < n2 Then  
  4.           minimum = n1  
  5.       Else  
  6.           minimum = n2  
  7.       End If  
  8.       For i As Long = minimum To 1 Step -1  
  9.           If n1 Mod i = 0 And n2 Mod i = 0 Then  
  10.               Return i  
  11.           End If  
  12.       Next  
  13. End Function  
Calculate a fraction

Here follows the routine that will calculate our fraction. It needs a decimal-type input parameter (as the 12.65 used previously).
  1. Public Function Calculate(value As DecimalAs String  
  2.         Dim intPart As Long = Math.Truncate(value)  
  3.         Dim numerator As Long = CType((value - intPart).ToString.Substring(2), Long)  
  4.         Dim denominator As Long = CType("1" & StrDup(numerator.ToString.Length, "0"), Long)  
  5.    
  6.         Dim _gcd As Long = gcd(numerator, denominator)  
  7.         Dim nDiv As Long = _gcd  
  8.    
  9.         While nDiv > 1  
  10.    
  11.             If numerator Mod nDiv = 0 And denominator Mod nDiv = 0 Then  
  12.                 numerator /= nDiv  
  13.                 denominator /= nDiv  
  14.                 nDiv = _gcd  
  15.             Else  
  16.                 nDiv -= 1  
  17.             End If  
  18.    
  19.         End While  
  20.    
  21.         Dim retVal As String = ""  
  22.         If intPart > 0 Then retVal = intPart.ToString & " + ("  
  23.         retVal &= numerator.ToString + " / " + denominator.ToString  
  24.         If intPart > 0 Then retVal &= ")"  
  25.         Return retVal  
  26. End Function  
The function will save the integral part of the number for later use, then proceed to calculate the maximum denominator, by adding a number of zeros to equal the number of decimal places. A call to our previously written GCD routine will compute the gretest Common Divisor between our numerator and denominator, entering a loop for dividing the numerator and denominator to determine their common divisors, until no common divisor is available.

Finally, having determined the simplyfied numerator and denominator, the routine will produce their string representation, joining the integral part. So, for our previous example of value = 12.65, the output will be: 12 + (13/20).

As the reader can note, in case no integral part is present, the fraction will be expressed without parenthesis.

Fraction class

The complete source for a reusable class can be the following:
  1. Public Class Fraction  
  2.    
  3.     Dim _value As Decimal  
  4.     Dim _fraction As String  
  5.    
  6.     Public ReadOnly Property Value As String  
  7.         Get  
  8.             Return _fraction  
  9.         End Get  
  10.     End Property  
  11.    
  12.     Public Property Number As Decimal  
  13.         Get  
  14.             Return _value  
  15.         End Get  
  16.         Set(value As Decimal)  
  17.             _value = value  
  18.             _fraction = Calculate(_value)  
  19.         End Set  
  20.     End Property  
  21.    
  22.     Public Sub New(value As Decimal)  
  23.         _value = value  
  24.         _fraction = Calculate(_value)  
  25.     End Sub  
  26.    
  27.     Public Sub New()  
  28.         _value = 0  
  29.         _fraction = 0  
  30.     End Sub  
  31.    
  32.     Private Function gcd(ByVal n1 As IntegerByVal n2 As IntegerAs Long  
  33.         Dim minimum As Long  
  34.         If n1 < n2 Then  
  35.             minimum = n1  
  36.         Else  
  37.             minimum = n2  
  38.         End If  
  39.    
  40.         For i As Long = minimum To 1 Step -1  
  41.             If n1 Mod i = 0 And n2 Mod i = 0 Then  
  42.                 Return i  
  43.             End If  
  44.         Next  
  45.     End Function  
  46.    
  47.     Public Function Calculate(value As DecimalAs String  
  48.         Dim intPart As Long = Math.Truncate(value)  
  49.         Dim numerator As Long = CType((value - intPart).ToString.Substring(2), Long)  
  50.         Dim denominator As Long = CType("1" & StrDup(numerator.ToString.Length, "0"), Long)  
  51.    
  52.         Dim _gcd As Long = gcd(numerator, denominator)  
  53.         Dim nDiv As Long = _gcd  
  54.    
  55.         While nDiv > 1  
  56.    
  57.             If numerator Mod nDiv = 0 And denominator Mod nDiv = 0 Then  
  58.                 numerator /= nDiv  
  59.                 denominator /= nDiv  
  60.                 nDiv = _gcd  
  61.             Else  
  62.                 nDiv -= 1  
  63.             End If  
  64.    
  65.         End While  
  66.    
  67.         Dim retVal As String = ""  
  68.         If intPart > 0 Then retVal = intPart.ToString & " + ("  
  69.         retVal &= numerator.ToString + " / " + denominator.ToString  
  70.         If intPart > 0 Then retVal &= ")"  
  71.         Return retVal  
  72.     End Function  
  73.    
  74. End Class  
In the source code that comes with that article, I've implemented a simple Windows Forms form, with a TextBox and some Labels, to show how the previous code works.



The code behind will be as simple as this:
  1. Public Class Form1  
  2.    
  3.     Dim f As New Fraction  
  4.    
  5.     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
  6.         f.Number = CType(TextBox1.Text, Decimal)  
  7.         Label3.Text = f.Value  
  8.     End Sub  
  9. End Class  
When the Button is clicked, the Number property of our Fraction class will be initialized with a cast towards Decimal type of what is contained in TextBox1.

Next, the property Value (that will contain our fraction string) will be shown in Label3.

Source Code

The sample code for this article can be downloaded from this link.