dcsimg
June 23, 2018
Hot Topics:

Implementing a Decimal-to-Fraction Class with Operator Overloading

  • August 15, 2007
  • By Paul Kimmel
  • Send Email »
  • More Articles »

Listing 1: The complete listing of the Fraction class.

Public Class  Fraction

   Public Sub New(ByVal number As Double)
      _number = Math.Round(number, 8)
      Dim value As String = _number.ToString()

      SetSign(value)
      Dim index As Integer = CheckNoDecimalPoint(number)
      If (index = -1) Then Return

      SetWholePart(value, index)
      SetFractionalPart(value, index)

   End Sub

   Public Shared Operator +(ByVal lhs As Fraction, _
                            ByVal rhs As Fraction) _
      As Fraction
      Return New Fraction(rhs.Number + lhs.Number)
   End Operator

   Public Shared Operator -(ByVal lhs As Fraction, _
                            ByVal rhs As Fraction) _
      As Fraction
      Return New Fraction(rhs.Number - lhs.Number)
   End Operator

   Public Shared Operator =(ByVal lhs As Fraction, _
                            ByVal rhs As Fraction) _
      As Boolean
      Return rhs.Number = lhs.Number
   End Operator

   Public Shared Operator <>(ByVal lhs As Fraction, _
                             ByVal rhs As Fraction) _
      As Boolean
      Return rhs.Number <> lhs.Number
   End Operator

   Public Shared Widening Operator CType(ByVal rhs As Fraction) _
      As Double
      Return rhs.Number
   End Operator

   Public Shared Operator /(ByVal lhs As Fraction, _
                            ByVal rhs As Fraction) _
      As Fraction
      Return New Fraction(rhs.Number / lhs.Number)
   End Operator

   Public Shared Operator *(ByVal lhs As Fraction, _
                            ByVal rhs As Fraction) _
      As Fraction
      Return New Fraction(rhs.Number * lhs.Number)
   End Operator

   Public Shared Narrowing Operator CType(ByVal number As Double) _
      As Fraction
      Return New Fraction(number)
   End Operator

   Public Sub New(ByVal number As String)
      Me.New(Convert.ToDouble(number))
   End Sub

   Private _number As Double
   Public Property Number() As Double
      Get
         Return _number
      End Get
      Set(ByVal Value As Double)
         _number = Value
      End Set
   End Property

   Private _sign As Integer = 1
   Public Property Sign() As Integer
      Get
         Return _sign
      End Get
      Set(ByVal Value As Integer)
         _sign = Value
      End Set
   End Property

   Private _numerator As Integer = 0
   Public Property Numerator() As Integer
      Get
         Return _numerator
      End Get
      Set(ByVal Value As Integer)
         _numerator = Value
      End Set
   End Property

   Private _denominator As Integer = 1
   Public Property Denominator() As Integer
      Get
         Return _denominator
      End Get
      Set(ByVal Value As Integer)
         _denominator = Value
      End Set
   End Property

   Private _fractionalNumber As Double
   Public Property FractionalNumber() As Double
      Get
         Return _fractionalNumber
      End Get
      Set(ByVal Value As Double)
         _fractionalNumber = Value
      End Set
   End Property

   Private _wholeNumber As Integer
   Public Property WholeNumber() As Integer
      Get
         Return _wholeNumber
      End Get
      Set(ByVal Value As Integer)
         _wholeNumber = Value
      End Set
   End Property

   Private Sub SetSign(ByVal value As String)

      If (Regex.IsMatch(value, "^-")) Then
         Sign = -1
      End If

   End Sub


   Private Function CheckNoDecimalPoint(ByVa number As Double) _
      As Integer

      Dim index As Integer = number.ToString().LastIndexOf(".")

      If (index = -1) Then
         WholeNumber = Convert.ToInt32(number)
      End If

      Return index

   End Function

   Private Sub SetWholePart(ByVal value As String, _
                            ByVal index As Integer)

      Dim whole As String = value.Substring(0, index)
      If (whole.Length > 0) Then
         WholeNumber = Convert.ToInt32(whole)
      End If

   End Sub

   Private Sub SetDenominator(ByVal fraction As String)
      Denominator = Math.Pow(10, fraction.Length)
   End Sub

   Private Sub SetFractionalPart(ByRef fraction As String)
      If (fraction.Length > 8) Then
         fraction = fraction.Substring(0, 8)
      End If

      _fractionalNumber = _
         Math.Round(Convert.ToDouble("." + fraction), 8)
   End Sub

   Private Sub SetFractionalPart(ByVal value As String, _
                                 ByVal index As Integer)

      Dim fraction As String = value.Remove(0, index + 1)

      If (fraction.Length > 0) Then
         SetFractionalPart(fraction)
         _numerator = Convert.ToInt32(fraction)
         SetDenominator(fraction)
         ReduceWithGcd()
      End If
   End Sub

   Private Sub ReduceWithGcd()

      Dim divisor As Integer = Gcd(_numerator, _denominator)
      _numerator   = _numerator / divisor
      _denominator = _denominator / divisor

   End Sub

   Private Function Gcd(ByVal num As Integer, _
                        ByVal den As Integer) As Integer

      If (den Mod num = 1) Then Return 1
      While (den Mod num <> 0)
         Dim temp As Integer = num
         num = den Mod num
         den = temp
      End While

      Return num

   End Function

   Public Overrides Function ToString() As String

      If (FractionalNumber = 0 And WholeNumber = 0) Then
         Return ""
      End If

      Dim builder As StringBuilder = New StringBuilder()
      If (Sign = -1) Then builder.Append("-")

      If (Math.Abs(WholeNumber) <> 0) Then

         If (FractionalNumber = 1) Then
            builder.Append(Math.Abs(WholeNumber) + 1)
            Return builder.ToString()
         Else
            builder.Append(Math.Abs(WholeNumber))
            builder.Append(" ")
         End If
      End If

      If (FractionalNumber <> 0) Then
         builder.Append(Numerator.ToString())
         builder.Append("/")
         builder.Append(Denominator.ToString())
      End If

      Return builder.ToString()
   End Function

End Class




Page 3 of 4



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

By submitting your information, you agree that developer.com may send you developer offers via email, phone and text message, as well as email offers about other products and services that developer believes may be of interest to you. developer will process your information in accordance with the Quinstreet Privacy Policy.

Sitemap

×
We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.
Thanks for your registration, follow us on our social networks to keep up-to-date