Grouping numbers with arrays
Hi guys!
Stuck on a bit of homework and hoping someone here could point me in the right direction.
This is the first question I've done (and It works fine btw!),
basically what it's doing is generating 100 random numbers, and then dividing each number by 10 to get a 1 digit number, this number is then used to count how many numbers per group are generated (for example, numbers between 0-9,10-19,20-29...etc) and then displaying them in a list box
Code:
Private Sub btn_generate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_generate.Click
Dim generator As Random = New Random(DateTime.Now.Millisecond)
Dim ageCount(0 To 99) As Short
Dim ageGroupNo As Short
Dim Age As Short
lst_output.Items.Clear()
lst_output.Items.Add("Age:" + vbTab + "Count:")
For i = 0 To 99 - For 100 iterations
Age = generator.Next(0, 100) - Generate a random num between 0-99
ageGroupNo = Age \ 10 - Divide number by 10
ageCount(ageGroupNo) += 1 - Increment Group
Next
Dim groups As New List(Of String)
For i = 0 To 9 - Generates group titles (0-9, 10-19...etc)
groups.Add(CStr(i * 10) + "-" + CStr((i * 10) + 9))
Next
For i = 0 To 9 - Displays data
lst_output.Items.Add(CStr(groups(i)) + vbTab + CStr(ageCount(i)))
Next
End Sub
so that's all well and good, but now the challenge
do the same thing but with 100 Decimal numbers between 1.0 and 2.75.
Code:
Private Sub btn_generate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_generate.Click
Dim generator As Random = New Random(DateTime.Now.Millisecond)
Dim heightCount(0 To 99) As Decimal
Dim heightGroupNo As Decimal
Dim Height As Decimal
lst_output.Items.Clear()
lst_output.Items.Add("Height:" + vbTab + "Count:")
For i = 0 To 99 - For 100 iterations
Generate:
Height = Math.Round(generator.NextDouble() * 2.75, 2) - Random Num no greater than 2.75
If Height < 1.0 Then - Make sure number is at least 1.0
GoTo Generate
End If
heightGroupNo = (Height / 0.9) - THIS is the problem part
heightCount(heightGroupNo) += 1
Next
For i = 0 To 8
lst_output.Items.Add(CStr(heightCount(i)))
Next
End Sub
I need the generated decimals to be broken into 9 groups
Code:
< 1.20
1.20 - 1.39
1.40 - 1.59
1.60 - 1.79
1.80 - 1.99
2.00 - 2.19
2.20 - 2.39
2.40 - 2.59
>2.60
I've tried converting the decimals to whole numbers and then dividing by 9, but nothing seems to be getting me the desired results, I tried a select/case statement, which worked but obviously inefficient as hell,
I know there's a better way to do it then that!
I get the feeling I'm missing something obvious and perhaps a fresh pair of eyes tomorrow morning will do the trick, but as it stands I'm pulling my hair out :P
thanks for your time, hope you can assist!
Re: Grouping numbers with arrays
array indices must be integer. here's an improvement for you. be sure to read the comments.
Code:
Public Class Form1
Private Sub btn_generate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_generate.Click
Dim generator As Random = New Random(DateTime.Now.Millisecond)
Dim ranges(,) As Decimal = {{1D, 1.19D}, {1.2D, 1.39D}, {1.4D, 1.59D}, {1.6D, 1.79D}, {1.8D, 1.99D}, {2D, 2.19D}, {2.2D, 2.39D}, {2.4D, 2.59D}, {2.6D, 2.75D}}
Dim heightCount(0 To 99) As Decimal
Dim heightGroupNo As Integer
Dim Height As Decimal
lst_output.Items.Clear()
lst_output.Items.Add("Height:" + vbTab + "Count:")
For i as Integer = 0 To 99 '- For 100 iterations
Do 'improvement here
Height = CDec(Math.Round(generator.NextDouble() * 2.75, 2)) '- Random Num no greater than 2.75
Loop While Height < 1D
heightGroupNo = getIndex(ranges, Height) '- fixed
If heightGroupNo = -1 Then i -= 1 : Continue For
heightCount(heightGroupNo) += 1
Next
For i = 0 To 8 'fixed outputting
lst_output.Items.Add(If(i = 0, "< 1.20", If(i = 8, "> 2.60", String.Format("{0:00} - {1}", ranges(i, 0), ranges(i, 1)))) & vbTab & CStr(heightCount(i)))
Next
End Sub
Private Function getIndex(ByVal d(,) As Decimal, ByVal value As Decimal) As Integer
For x As Integer = 0 To d.GetUpperBound(0)
If value >= d(x, 0) And value <= d(x, 1) Then Return x
Next
Return -1
End Function
End Class
Re: Grouping numbers with arrays
Because the differences between groups are not the same (1st group is 1.2 while other groups is only 0.2), you need to use select case or if...elseif...esle statement.
Re: Grouping numbers with arrays
I'm not sure about the exact speed benefit, but what I would try would be generating random numbers between 0 and your maximum size. Basically, if you took all of your categories and multiplied by 100, you'd be converting all of your categories into integers.
You could then make an array of Integer equal to the range of numbers you wanted to generate. Yeah, it might be 1000, or more, but so what, memory is cheap. Your loop would then look like this:
Code:
For x = 0 to 99
yourArray(generator.Next(maxValue)) +=1
Next
Then you'd just sum up your ranges with a series of loops, one per category. The first loop would look like this:
Code:
Dim sum as Integer
For x = 0 to 119
sum += yourArray(x)
Next
The pieces are totally trivial, as there are no conversions and no conditionals in the whole code. The code trades memory for speed. The drawback would be that with only 100 items, a very large number of the array slots would be 0, so you'd be performing a bunch of extra += 0 statements, but you'd have to test it to see whether or not it mattered. I would expect that the first loop would cost more in time than all the others, regardless of the number of categories you used, just because of the cost of the random number generator.
Re: Grouping numbers with arrays
Wow, brilliant guys,
thanks a lot to all of you!, you've taught me more than you know in a single post, I really appreciate it! :D