# accepting, then displaying fractions

### Question

• I am currently working on a program for work that accepts fractional numbers from the user, and displays the result using the same format. Converting to decimal is the easy part. I need some input as to how I can convert back to a fraction using different resolutions(1/16, 1/32, 1/64...etc) based on how close the answer is to a list of decimal numbers. Thank you.
Saturday, July 04, 2009 4:00 PM

• I found a QBASIC program for converting decimal numbers to fractions.  I didn't write it, but I translated the code into something that will run inside a VB Console application.  Check this out to see if it works for you:

```Module Module1

Sub Main()
'translated by Solitaire from QBasic code originally written by lawgin
Dim min, d1, p, dp, wp, m, x1, x2, dx, y, d2 As Double
Dim d As String
min = 10
Console.Write("Enter decimal:  ")
p = Len(d) - InStr(d, ".") + 1
d1 = Val(d)
wp = Int(d1)
dp = d1 - wp
Do
m = m + 1
x1 = m * dp
x2 = CLng(x1)
dx = Math.Abs(x1 - x2)
If dx < min Then
min = dx
y = m
d2 = (CLng(y * dp) + y * wp) / y
End If
Loop Until Math.Abs(d2 - d1) < 1 / 10 ^ p
Console.WriteLine(d1 & " = " & CLng(y * dp) + y * wp & "/" & y)
End Sub

End Module```

Solitaire
Sunday, July 05, 2009 2:55 AM
• Saturday, July 04, 2009 5:00 PM
• Saturday, July 04, 2009 5:12 PM
• Hi Solitare

hmm... I get my code to work but in obviuse cases it does not show the value im expekt.... My lates attemt to create a own struct is shown below.... I have also implemented the transleted code from lawgin you provided... but I couldnt get it to work properly

```Public Structure Fractions
Public pHoleNumber As Integer
Public pDevicor As Integer
Public pNummorator As Integer

Public Sub New(ByVal HoleNumber As Integer, ByVal Nummorator As Integer, ByVal Devicor As Integer)
pNummorator = Nummorator
pHoleNumber = HoleNumber
pDevicor = Devicor
End Sub

Public Sub New(ByVal Nummorator As Integer, ByVal Devicor As Integer)
pNummorator = Nummorator
pDevicor = Devicor
End Sub

Public Sub New(ByVal Desimal As Double, ByVal bool As Boolean)
Dim result As New Fractions
If bool = True Then
Dim d As Double = Desimal
result.HoleNumber = Math.Floor(d)
Dim test As Double = d - CDbl(result.HoleNumber)
For i As Integer = 1 To 1000
For j As Integer = 1 To 10000
If i / j = test Or i / j - test < Double.Epsilon Then
result.Nummorator = i
result.Devicor = j
Dim counter As Integer = 0
If result.Nummorator < result.Devicor Then
counter = result.Nummorator
Else
counter = result.Devicor
End If

For a = 2 To counter
If result.Nummorator Mod a = 0 Then
If result.Devicor Mod a = 0 Then
result.Nummorator /= a
result.Devicor /= a
End If
End If
Next
Exit For
Exit For
End If
Next
Next

Else
'Solitare translation of lawgin code
Dim min, d1, p, dp, wp, m, x1, x2, dx, y, d2 As Double
Dim d As String
min = 10

d = Desimal
p = Len(d) - InStr(d, ".") + 1
d1 = Val(d)
wp = Int(d1)
dp = d1 - wp
Do
m = m + 1
x1 = m * dp
x2 = CLng(x1)
dx = Math.Abs(x1 - x2)
If dx < min Then
min = dx
y = m
d2 = (CLng(y * dp) + y * wp) / y
End If
Loop Until Math.Abs(d2 - d1) < 1 / 10 ^ p

result.HoleNumber = CLng(y * dp)
result.Nummorator = y * wp
result.Devicor = y
End If

Me.HoleNumber = result.HoleNumber
Me.Nummorator = result.Nummorator
Me.Devicor = result.Devicor
End Sub

Public Property Nummorator() As Integer
Get
Return pNummorator
End Get
Set(ByVal value As Integer)
pNummorator = value
End Set
End Property

Public Property Devicor() As Integer
Get
Return pDevicor
End Get
Set(ByVal value As Integer)
pDevicor = value
End Set
End Property

Public Property HoleNumber() As Integer
Get
Return pHoleNumber
End Get
Set(ByVal value As Integer)
pHoleNumber = value
End Set
End Property

Public Overloads Overrides Function ToString() As String
Return pHoleNumber & " " & pNummorator & "/" & pDevicor
End Function

' Unary operators:
Public Shared Operator +(ByVal c As Fractions) As Fractions
Return c
End Operator

Public Shared Operator -(ByVal c As Fractions) As Fractions
Return New Fractions(c.HoleNumber, c.Nummorator, c.Devicor)
End Operator

Public Overloads Shared Operator +(ByVal N1 As Fractions, ByVal N2 As Fractions) As Fractions
Dim hole As Integer = N1.pHoleNumber + N2.pHoleNumber
Dim commonDev As Integer = N1.pDevicor * N2.pDevicor
Dim commonNum As Integer = N1.pNummorator * N2.pDevicor + N2.pNummorator * N1.pDevicor

Dim n As Integer = Math.Floor(commonNum / commonDev)
If n >= 1 Then
hole += n
commonNum -= n * commonDev
End If
Dim counter As Integer = 0
If commonNum < commonDev Then
counter = commonNum
Else
counter = commonDev
End If

For a = 2 To counter
If commonNum Mod a = 0 Then
If commonDev Mod a = 0 Then
commonNum /= a
commonDev /= a
End If
End If
Next

Dim result As New Fractions(hole, commonNum, commonDev)
Return result
End Operator
End Structure```
Feel free to have a go at it... Here is a test example:

``` TextBox6.Text = CDbl(TextBox4.Text) + CDbl(TextBox3.Text)
Dim f As New Fractions(CDbl(TextBox3.Text), True)
Dim ff As New Fractions(CDbl(TextBox4.Text), True)
Dim g As New Fractions
g = f + ff
TextBox5.Text = g.ToString```

Kenneth
Sunday, July 05, 2009 4:06 AM

### All replies

• It wont work... you have to round the numbers if you want to do this.... or youll have to calculate with fractions...
but that implice that youll have to construct a class to do it for you... not impossible but much work... I dont know of any such class in .net libraries though

Kenneth
Saturday, July 04, 2009 4:49 PM
• Saturday, July 04, 2009 5:00 PM
• Saturday, July 04, 2009 5:12 PM
• rick
actually, this might work for you.
when you put the fraction into the textbox, convert it to a decimal and store that value.
then to convert back to a fraction, loop through the numbers until a match is made with the decimal from before.

I tried this on a lot of numbers and it was correct on all of them. need a form with 1 textbox to input the fraction and 2 buttons - 1 to convert the fraction to a decimal and 1 to go back

```Dim testnum As Double
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Dim dvnd As Double
Dim dvsr As Double

Dim strDvnd As String
Dim strDvsr As String
If TextBox1.TextLength > 2 AndAlso TextBox1.Text.Contains("/") Then
strDvnd = TextBox1.Text.Substring(0, TextBox1.Text.IndexOf("/"))
strDvsr = TextBox1.Text.Substring((TextBox1.Text.IndexOf("/") + 1))
Else
MessageBox.Show("You must enter a valid fraction")
Exit Sub
End If

Double.TryParse(strDvnd, dvnd)
Double.TryParse(strDvsr, dvsr)
testnum = dvnd / dvsr
MessageBox.Show(testnum.ToString)

End Sub

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
For i As Integer = 1 To 9
For j As Integer = 2 To 64
If i / j = testnum Then
MessageBox.Show("the fraction is " & i.ToString & "/" & j.ToString)
'Exit Sub 'uncomment this if you want only the reduced fraction
End If
Next
Next
End Sub```
Sunday, July 05, 2009 12:30 AM
• Hi

Nice work jwavila....

But it has some limitations on the fractions that you can recover but that is just a matter of how precice you need them Id guess

Kenneth
Sunday, July 05, 2009 12:39 AM
• If you change the for statment to this it might always give you an answer

```    If i / j = testnum Or i / j - testnum < Double.Epsilon Then
MessageBox.Show("the fraction is " & i.ToString & "/" & j.ToString)
'Exit Sub 'uncomment this if you want only the reduced fraction
End If```
And in addition ... Lets say you wright alarge fraction like 468 / 81 your program wouldnt cop with it unless you did something like this

testnum = dvnd / dvsr - Cint(dvnd / dvsr)
and add another variabel for the hole fraction

dim holenumner = Cint(dvnd / dvsr)

Kenneth
Sunday, July 05, 2009 12:47 AM
• well if you notice I cut off the bottom number at 64. I also tried it up to 1000 and everything worked OK. Didn't miss any of them.

I don't know if it will stand the test of time, however.

Do me a favor and change the j = 2 to whatever number you want and then try it.

Thanks
Sunday, July 05, 2009 1:00 AM
• well if you notice I cut off the bottom number at 64. I also tried it up to 1000 and everything worked OK. Didn't miss any of them.

I don't know if it will stand the test of time, however.

Do me a favor and change the j = 2 to whatever number you want and then try it.

Thanks

Way beond you ;-) Ill post in a secound
Kenneth
Sunday, July 05, 2009 1:05 AM
• Hi

paste inn this class... It still misses something but you can easely add that

```Public Class Fractions
Private pHoleNumber As Integer
Private pDevicor As Integer
Private pNummorator As Integer

Public Sub New()

End Sub

Public Sub New(ByVal HoleNumber As Integer, ByVal Nummorator As Integer, ByVal Devicor As Integer)
pNummorator = Nummorator
pHoleNumber = HoleNumber
pDevicor = Devicor
End Sub

Public Sub New(ByVal Nummorator As Integer, ByVal Devicor As Integer)
pNummorator = Nummorator
pDevicor = Devicor
End Sub

Public Sub New(ByVal Desimal As Double)
pHoleNumber = CInt(Math.Floor(Desimal))
Dim test As Double = Desimal - CInt(Math.Floor(Desimal))

For i As Integer = 1 To 100
For j As Integer = 1 To 1000
If i / j = test Then
pNummorator = i
pDevicor = j
Exit For
Exit For
End If
Next
Next
End Sub

Public Overloads Function ToString() As String
Return pHoleNumber & " " & pNummorator & "/" & pDevicor
End Function

Public Overloads Shared Operator +(ByVal N1 As Fractions, ByVal N2 As Fractions) As Fractions
Dim hole As Integer = N1.pHoleNumber + N2.pHoleNumber
Dim commonDev As Integer = N1.pDevicor * N2.pDevicor
Dim commonNum As Integer = N1.pNummorator * N2.pDevicor + N2.pNummorator * N1.pDevicor
Dim result As New Fractions(hole, commonNum, commonDev)
Return result
End Operator

Public Property Nummorator() As Integer
Get
Return pNummorator
End Get
Set(ByVal value As Integer)
pNummorator = value
End Set
End Property

Public Property Devicor() As Integer
Get
Return pDevicor
End Get
Set(ByVal value As Integer)
pDevicor = value
End Set
End Property

Public Property HoleNumber() As Integer
Get
Return pHoleNumber
End Get
Set(ByVal value As Integer)
pHoleNumber = value
End Set
End Property
End Class```

Kenneth
Sunday, July 05, 2009 1:38 AM
• Hi just a little ting ... this will work even better

``` For i As Integer = 1 To 100
For j As Integer = 1 To 1000
If i / j = test Then
pNummorator = i
pDevicor = j
Dim counter As Integer = 0
If pNummorator < pDevicor Then
counter = pNummorator
Else
Counter = pDevicor
End If

For a = 2 To Counter
If pNummorator Mod a = 0 Then
If pDevicor Mod a = 0 Then
pNummorator /= a
pDevicor /= a
End If
End If
Next
Exit For
Exit For
End If
Next
Next```

Kenneth
Sunday, July 05, 2009 1:57 AM
• hmm

Not perfect... It does something strange when you put in double values.... and they dont get the right value input.... Could someone please check this?
Kenneth
Sunday, July 05, 2009 2:49 AM
• I found a QBASIC program for converting decimal numbers to fractions.  I didn't write it, but I translated the code into something that will run inside a VB Console application.  Check this out to see if it works for you:

```Module Module1

Sub Main()
'translated by Solitaire from QBasic code originally written by lawgin
Dim min, d1, p, dp, wp, m, x1, x2, dx, y, d2 As Double
Dim d As String
min = 10
Console.Write("Enter decimal:  ")
p = Len(d) - InStr(d, ".") + 1
d1 = Val(d)
wp = Int(d1)
dp = d1 - wp
Do
m = m + 1
x1 = m * dp
x2 = CLng(x1)
dx = Math.Abs(x1 - x2)
If dx < min Then
min = dx
y = m
d2 = (CLng(y * dp) + y * wp) / y
End If
Loop Until Math.Abs(d2 - d1) < 1 / 10 ^ p
Console.WriteLine(d1 & " = " & CLng(y * dp) + y * wp & "/" & y)
End Sub

End Module```

Solitaire
Sunday, July 05, 2009 2:55 AM
• Hi Solitare

hmm... I get my code to work but in obviuse cases it does not show the value im expekt.... My lates attemt to create a own struct is shown below.... I have also implemented the transleted code from lawgin you provided... but I couldnt get it to work properly

```Public Structure Fractions
Public pHoleNumber As Integer
Public pDevicor As Integer
Public pNummorator As Integer

Public Sub New(ByVal HoleNumber As Integer, ByVal Nummorator As Integer, ByVal Devicor As Integer)
pNummorator = Nummorator
pHoleNumber = HoleNumber
pDevicor = Devicor
End Sub

Public Sub New(ByVal Nummorator As Integer, ByVal Devicor As Integer)
pNummorator = Nummorator
pDevicor = Devicor
End Sub

Public Sub New(ByVal Desimal As Double, ByVal bool As Boolean)
Dim result As New Fractions
If bool = True Then
Dim d As Double = Desimal
result.HoleNumber = Math.Floor(d)
Dim test As Double = d - CDbl(result.HoleNumber)
For i As Integer = 1 To 1000
For j As Integer = 1 To 10000
If i / j = test Or i / j - test < Double.Epsilon Then
result.Nummorator = i
result.Devicor = j
Dim counter As Integer = 0
If result.Nummorator < result.Devicor Then
counter = result.Nummorator
Else
counter = result.Devicor
End If

For a = 2 To counter
If result.Nummorator Mod a = 0 Then
If result.Devicor Mod a = 0 Then
result.Nummorator /= a
result.Devicor /= a
End If
End If
Next
Exit For
Exit For
End If
Next
Next

Else
'Solitare translation of lawgin code
Dim min, d1, p, dp, wp, m, x1, x2, dx, y, d2 As Double
Dim d As String
min = 10

d = Desimal
p = Len(d) - InStr(d, ".") + 1
d1 = Val(d)
wp = Int(d1)
dp = d1 - wp
Do
m = m + 1
x1 = m * dp
x2 = CLng(x1)
dx = Math.Abs(x1 - x2)
If dx < min Then
min = dx
y = m
d2 = (CLng(y * dp) + y * wp) / y
End If
Loop Until Math.Abs(d2 - d1) < 1 / 10 ^ p

result.HoleNumber = CLng(y * dp)
result.Nummorator = y * wp
result.Devicor = y
End If

Me.HoleNumber = result.HoleNumber
Me.Nummorator = result.Nummorator
Me.Devicor = result.Devicor
End Sub

Public Property Nummorator() As Integer
Get
Return pNummorator
End Get
Set(ByVal value As Integer)
pNummorator = value
End Set
End Property

Public Property Devicor() As Integer
Get
Return pDevicor
End Get
Set(ByVal value As Integer)
pDevicor = value
End Set
End Property

Public Property HoleNumber() As Integer
Get
Return pHoleNumber
End Get
Set(ByVal value As Integer)
pHoleNumber = value
End Set
End Property

Public Overloads Overrides Function ToString() As String
Return pHoleNumber & " " & pNummorator & "/" & pDevicor
End Function

' Unary operators:
Public Shared Operator +(ByVal c As Fractions) As Fractions
Return c
End Operator

Public Shared Operator -(ByVal c As Fractions) As Fractions
Return New Fractions(c.HoleNumber, c.Nummorator, c.Devicor)
End Operator

Public Overloads Shared Operator +(ByVal N1 As Fractions, ByVal N2 As Fractions) As Fractions
Dim hole As Integer = N1.pHoleNumber + N2.pHoleNumber
Dim commonDev As Integer = N1.pDevicor * N2.pDevicor
Dim commonNum As Integer = N1.pNummorator * N2.pDevicor + N2.pNummorator * N1.pDevicor

Dim n As Integer = Math.Floor(commonNum / commonDev)
If n >= 1 Then
hole += n
commonNum -= n * commonDev
End If
Dim counter As Integer = 0
If commonNum < commonDev Then
counter = commonNum
Else
counter = commonDev
End If

For a = 2 To counter
If commonNum Mod a = 0 Then
If commonDev Mod a = 0 Then
commonNum /= a
commonDev /= a
End If
End If
Next

Dim result As New Fractions(hole, commonNum, commonDev)
Return result
End Operator
End Structure```
Feel free to have a go at it... Here is a test example:

``` TextBox6.Text = CDbl(TextBox4.Text) + CDbl(TextBox3.Text)
Dim f As New Fractions(CDbl(TextBox3.Text), True)
Dim ff As New Fractions(CDbl(TextBox4.Text), True)
Dim g As New Fractions
g = f + ff
TextBox5.Text = g.ToString```

Kenneth
Sunday, July 05, 2009 4:06 AM
• Hmm...

Ive been doing some thinking ... Its unusual for me... ;-) And there is ofcource a different way of getting a fraction then the ones that are mention above....

Metod 1:
Lets say you have a texte box and you want to write in the irrational number PI.... There is ofcourse a simple way of turnig the number Pi into a fraction...
dim txtStr as String = TextInput
dim Chords as String() = txtStr.Split(",") or by . in english
you will then have the Integer in Chords(0) and in Chords(1) you will have all the numbers after decimal point.

the nummorator can thus be set to Chords(1) and the denummorator will the become 10^(Chords(1).length). I think this is a way for irrational numbers, becouse you will never or seldom get a nice fraction from them....

Method 2: the on that is been shown in this thread before... They work well for rational numbers or numbers that a cumbersome in decimal and nice in fractions.

The Ideal solution, in my mind is to combine the two methods in one... You might first check if you willl get a nice fraction with method 2... And if thats not the case you can always go for method 1.

With method 1 there is a possibilyuty that you could factor it down. I have modified a code for doning that and it baisially sees if the same mod a goes for nummorator and denummorator.

``` Dim counter As Integer = Math.Max(commonDev, commonNum)
Dim a As Integer = 2
While a < commonNum Or commonDev > a
If commonNum Mod a = 0 Then
If commonDev Mod a = 0 Then
commonNum = commonNum / a
commonDev = commonDev / a
a = 2
Else
a += 1
End If
Else
a += 1
End If
End While```
For a simple program, designing a struct or a class that holds all the fractions might be a little overkill. but i you do it properly it will work on every occation. I have corrected som bad coding mistakes in it and it wont work properly the way it is displaied here.

Kenneth
Tuesday, July 07, 2009 8:05 PM