Module Module1

    Sub Main()
        Dim f1 As New Fraction(2, 3)
        Dim f2 As New Fraction(1, 4)

        Console.WriteLine("f1 = " & f1.ToString())
        Console.WriteLine("f2 = " & f2.ToString())

        Dim f3 As Fraction
        f3 = f1 + f2     ' f3 obecnie wynosi 11/12
        Console.WriteLine("f1 + f2 = " & f3.ToString())

        f3 = f1 / f2     ' f3 obecnie wynosi 8/3
        Console.WriteLine("f1 / f2 = " & f3.ToString())

        f3 = f1 - f2     ' f3 obecnie wynosi 5/12
        Console.WriteLine("f1 - f2 = " & f3.ToString())

        f3 = f1 * f2     ' f3 obecnie wynosi 1/6
        Console.WriteLine("f1 * f2 = " & f3.ToString())
        Console.ReadLine()

    End Sub

End Module

Public Structure Fraction

    ' Dwie części ułamka
    Public Denominator As Integer
    Public Numerator As Integer

    Public Sub New(ByVal numerator As Integer, ByVal denominator As Integer)
        Me.Numerator = numerator
        Me.Denominator = denominator
    End Sub

    Public Shared Operator +(ByVal x As Fraction, ByVal y As Fraction) _
      As Fraction
        Return Normalize(x.Numerator * y.Denominator + _
          y.Numerator * x.Denominator, x.Denominator * y.Denominator)
    End Operator

    Public Shared Operator -(ByVal x As Fraction, ByVal y As Fraction) _
      As Fraction
        Return Normalize(x.Numerator * y.Denominator - _
          y.Numerator * x.Denominator, x.Denominator * y.Denominator)
    End Operator

    Public Shared Operator *(ByVal x As Fraction, ByVal y As Fraction) _
      As Fraction
        Return Normalize(x.Numerator * y.Numerator, _
          x.Denominator * y.Denominator)
    End Operator

    Public Shared Operator /(ByVal x As Fraction, ByVal y As Fraction) _
      As Fraction
        Return Normalize(x.Numerator * y.Denominator, _
          x.Denominator * y.Numerator)
    End Operator

    ' Redukcja ułamka
    Private Shared Function Normalize(ByVal numerator As Integer, _
      ByVal denominator As Integer) As Fraction
        If (numerator <> 0) And (denominator <> 0) Then
            ' Poprawianie znaków
            If denominator < 0 Then
                denominator *= -1
                numerator *= -1
            End If

            Dim divisor As Integer = GCD(numerator, denominator)
            numerator \= divisor
            denominator \= divisor
        End If

        Return New Fraction(numerator, denominator)
    End Function

    ' Zwracanie największego wspólnego dzielnika przy użyciu algorytmu Euklidesa
    Private Shared Function GCD(ByVal x As Integer, ByVal y As Integer) _
      As Integer
        Dim temp As Integer

        x = Math.Abs(x)
        y = Math.Abs(y)
        Do While (y <> 0)
            temp = x Mod y
            x = y
            y = temp
        Loop

        Return x
    End Function

    ' Przekształcanie ułamka w postać dziesiętną
    Public Function GetDouble() As Double
        Return CType(Me.Numerator, Double) / _
          CType(Me.Denominator, Double)
    End Function

    ' Pobieranie łańcucha reprezentującego ułamek
    Public Overrides Function ToString() As String
        Return Me.Numerator.ToString & "/" & Me.Denominator.ToString
    End Function

End Structure
