How can I identify an infinitely recurring decimal?
For example…
Dim result as Decimal = CDec(1/3)
Edit: Or just recurring decimals?
?
Printable View
How can I identify an infinitely recurring decimal?
For example…
Dim result as Decimal = CDec(1/3)
Edit: Or just recurring decimals?
?
I'm not sure that there is a general case. There might be a way to be pretty sure for the simpler cases like 1/3 or 2/3, but it seems like other cases would be pretty dicey in computers. After all, some repeating decimals can look an awful lot like floating point imprecision.
What is the purpose behind it? Perhaps there is some other way to finesse a solution.
It’s a betting calculator. Given 2 values from {odds, stake, profit} I need to be able to calculate the 3rd value. I have it to the point where I can calculate all 3, and for the calculation to find odds, I have 2 different methods. One that works well with recurring profit values, and one that works perfectly with more simple calculations. Both of the methods are good in one scenario, and useless in the other scenario…? So it would be helpful to determine if a number is a recurring decimal…
I’m not at my computer at the moment, and VBForums won’t work in Chrome (I have to use Edge). I’ll have to change my password to sign in with Edge before I can post the code I have…
Where do the numbers come from? Are the numerator and denominator always going to be integers?
Given integers a and b, where neither a or b are equal to 0, assuming a and b are relatively prime (a/b is in "lowest terms"), then if b has any prime factors other than 2 or 5, then a/b is a repeating decimal. If b has only prime factors of 2 and 5 then a/b has a finite decimal representation.
The 2 values for numerator and denominator could be 10/13.3333 or any number. I can double both values repeatedly in a loop until they are both Integers. But that doesn’t work so well with recurring decimals
*Or multiply them by 10 :D
Can you explain why it matters with whatever you are calculating? How does 1/3 present an issue vs. 1/2?
1/2 is easy to calculate. It’s easy to simplify.
1/3 ends up as something like 1000000000/333333333 if I don’t use the right function. The problem I’m having with some numbers is that it crashes my app if I don’t identify it early, and I can’t work out a simple way to catch it…
Obviously that’s not an acceptable fraction. But it’s not just about acceptable fractions. I need to identify a recurring decimal to avoid running my simplifying code that crashes the app, because the numbers end up too large for my integer simplifying code. I’ll post the code…
Code:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim edTB1 As EnableDisableTextBox = EnableDisableTextBox1 ''
Dim edTB2 As EnableDisableTextBox = EnableDisableTextBox2 '' These are just TextBoxes restricted for decimal input or fractional input
Dim edTB3 As EnableDisableTextBox = EnableDisableTextBox3 '' in the edTB1 case
Dim odds(1) As Integer
Dim stake As Decimal
Dim profit As Decimal
If edTB1.Checked And edTB2.Checked Then
Dim parts() As String = edTB1.Text.Split(New Char() {"/"c}, StringSplitOptions.RemoveEmptyEntries)
If parts.Count = 2 AndAlso Integer.TryParse(parts(0), odds(0)) AndAlso Integer.TryParse(parts(1), odds(1)) AndAlso Decimal.TryParse(edTB2.Text, stake) AndAlso odds(0) > 0 AndAlso odds(1) > 0 Then
Dim x As Decimal = stake / odds(1) * odds(0)
edTB3.Text = x.ToString
End If
ElseIf edTB1.Checked And edTB3.Checked Then
Dim parts() As String = edTB1.Text.Split(New Char() {"/"c}, StringSplitOptions.RemoveEmptyEntries)
If parts.Count = 2 AndAlso Integer.TryParse(parts(0), odds(0)) AndAlso Integer.TryParse(parts(1), odds(1)) AndAlso Decimal.TryParse(edTB3.Text, profit) AndAlso odds(0) > 0 AndAlso odds(1) > 0 Then
Dim x As Decimal = profit / odds(0) * odds(1)
edTB2.Text = x.ToString
End If
ElseIf edTB2.Checked And edTB3.Checked Then
If Decimal.TryParse(edTB2.Text, stake) AndAlso Decimal.TryParse(edTB3.Text, profit) AndAlso stake > 0 AndAlso profit > 0 Then
Dim s As Decimal = stake
Dim p As Decimal = profit
While s Mod 1 <> 0
s *= 10
p *= 10
End While
While p Mod 1 <> 0
s *= 10
p *= 10
End While
If s > Integer.MaxValue Or p > Integer.MaxValue Then '' This is where i'm having trouble
edTB1.Text = MakeFraction(CDec(profit / stake)) '' MakeFraction works well with numbers like 1/3
Else
For x As Integer = Math.Max(s, p) To 1 Step -1
If (s / x) Mod 1 = 0 And (p / x) Mod 1 = 0 Then
s /= x
p /= x
End If
Next
edTB1.Text = String.Format("{0}/{1}", p, s) '' this works well with finite numbers
End If
End If
End If
End Sub
It’s only a tiny app. I can post the entire app if necessary. The current (first block) code I posted doesn’t catch recurring numbers. It should only call MakeFraction in recurring cases. In any other cases, MakeFraction returns invalid oddsCode:
Function MakeFraction(ByVal DecimalNumber As Decimal) As String
Dim tolerance As Double = 0.1 'Fraction has to be at least this close'
'Dim decimalValue As Double = 0.125 'Original value to convert'
Dim highestDenominator = 100 'Highest denominator you`re willing to accept'
Dim denominator As Integer
For denominator = 2 To highestDenominator - 1
'Find the closest numerator'
Dim numerator As Integer = Math.Round(denominator * DecimalNumber)
'Check if the fraction`s close enough'
If Math.Abs(numerator / denominator - DecimalNumber) <= tolerance Then
Return numerator & "/" & denominator
End If
Next
'Didn't find one. Use the highest possible denominator'
Return Math.Round(denominator * DecimalNumber) & "/" & highestDenominator
End Function
My gut instinct is that you are needlessly overcomplicating this, but I'm not familiar enough with betting odds calculation to know for sure.
So, there is some sort of formula involving odds, stake, and profit. You are getting any 2 of those 3 values and need to be able to calculate the third value? What is the underlying mathematical formula involved that ties all three of those values together?
Edit: Can you give a couple examples with "troublesome" numbers, and what the "good" results should be? That would help me understand what you are looking for.
Here’s the complete app, with a simple GUI. Troublesome numbers are those where profit/stake results in an infinitely recurring decimal
Attachment 195889
Edit: As I’ve said, I have 2 methods for calculating odds. Both work well with different types of decimals, so I can’t use a sweeping algorithm. My intended solution is to identify the 2 types of decimals, so I can use the best algorithm to work out the odds…
Thanks for the suggestions. I tried a slightly different tack, and now it works a lot better…
The code I posted here wasn’t exactly descriptive of the progress I’d made, and would probably crash if you tried to run it.