Answered by:
accepting, then displaying fractions

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
Question
Answers

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: ") d = Console.ReadLine() 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) Console.ReadLine() End Sub End Module
Solitaire Proposed as answer by Kenneth Haugland Sunday, July 05, 2009 6:43 PM
 Marked as answer by Riquel_DongModerator Friday, July 10, 2009 8:00 AM
Sunday, July 05, 2009 2:55 AM 
can't help any more than this link about the same:
http://social.msdn.microsoft.com/Forums/enUS/Vsexpressvb/thread/34dde7091f25422a9141939abfffe7e5 Marked as answer by Riquel_DongModerator Friday, July 10, 2009 8:00 AM
Saturday, July 04, 2009 5:00 PM 
Hi
or do this just with fractions insted of LargeNumbers
http://social.msdn.microsoft.com/Forums/enUS/vbgeneral/thread/14a03093334c4adcbaaba5e628de2951
Kenneth Marked as answer by Riquel_DongModerator Friday, July 10, 2009 8:00 AM
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 Marked as answer by Riquel_DongModerator Friday, July 10, 2009 8:03 AM
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
KennethSaturday, July 04, 2009 4:49 PM 
can't help any more than this link about the same:
http://social.msdn.microsoft.com/Forums/enUS/Vsexpressvb/thread/34dde7091f25422a9141939abfffe7e5 Marked as answer by Riquel_DongModerator Friday, July 10, 2009 8:00 AM
Saturday, July 04, 2009 5:00 PM 
Hi
or do this just with fractions insted of LargeNumbers
http://social.msdn.microsoft.com/Forums/enUS/vbgeneral/thread/14a03093334c4adcbaaba5e628de2951
Kenneth Marked as answer by Riquel_DongModerator Friday, July 10, 2009 8:00 AM
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
 Proposed as answer by Kenneth Haugland Sunday, July 05, 2009 6:43 PM
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
KennethSunday, 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)
KennethSunday, 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.
ThanksSunday, 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
KennethSunday, 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
KennethSunday, 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
KennethSunday, 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?
KennethSunday, 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: ") d = Console.ReadLine() 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) Console.ReadLine() End Sub End Module
Solitaire Proposed as answer by Kenneth Haugland Sunday, July 05, 2009 6:43 PM
 Marked as answer by Riquel_DongModerator Friday, July 10, 2009 8:00 AM
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 Marked as answer by Riquel_DongModerator Friday, July 10, 2009 8:03 AM
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.
KennethTuesday, July 07, 2009 8:05 PM