|
-
May 14th, 2020, 02:36 PM
#1
Thread Starter
New Member
Loop while help
Hello, i need to make my program pick 3 different numbers, but they all have to be different numbers, i know that number1 and number2 wont be the same but how to i make it check if it is equal to 2 variables for example ("Loop While (bteNombre3 = 2 variables)"). The code below is what i have so far and i need to figure out the last line, thanks!!
Randomize()
bteNombre1 = Int(9 * Rnd() + 1)
Do
Randomize()
bteNombre2 = Int(9 * Rnd() + 1)
Loop While (bteNombre1 = bteNombre2)
Do
Randomize()
bteNombre3 = Int(9 * Rnd() + 1)
Loop While (bteNombre3 is equal to bteNombre1 or bteNombre2??)
-
May 14th, 2020, 03:01 PM
#2
Thread Starter
New Member
Re: Loop while help
Nevermind lol i found my answer, we can close this thread. (OrElse)
-
May 14th, 2020, 04:03 PM
#3
Re: Loop while help
I hope the answer involved getting rid of pretty much all that code. You are misusing Randomize in a way that will make those numbers anything but random, and you shouldn't be using either Rnd or Randomize anyways. Those are legacy. Create one Random object at form scope.
The problem you have with Randomize is that it re-seeds the random number generator with the system time down to the second. Two sequences with the same seed will be the same sequence. Therefore, by calling Randomize in a tight loop, you keep starting over with the same sequence. So, each time you get the first value from a sequence, then throw out the sequence and get a new sequence...which happens to be the exact same as the old sequence as long as the system time hasn't advanced by one second. So, if you get 5 the first time, then you will keep getting 5 over and over and over until the system time advances by one second.
Now, eventually, that WILL work, because it will run over and over and over, with the numbers being identical. However, eventually it will have run for a full second, and the sequence will change. The loops may have run for hundreds of thousands of iterations, but eventually, you will get a new number...at a rate of one per second.
My usual boring signature: Nothing
 
-
May 14th, 2020, 06:08 PM
#4
Re: Loop while help
This would work...
Code:
Public Class Form1
Dim r As New Random
'..........
Code:
Dim numbers As New List(Of Integer)(New Integer() {1, 2, 3, 4, 5, 6, 7, 8, 9})
Dim bteNombre1 As Integer = numbers(r.Next(0, numbers.Count))
numbers.Remove(bteNombre1)
Dim bteNombre2 As Integer = numbers(r.Next(0, numbers.Count))
numbers.Remove(bteNombre2)
Dim bteNombre3 As Integer = numbers(r.Next(0, numbers.Count))
numbers.Remove(bteNombre3)
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
May 14th, 2020, 09:52 PM
#5
Re: Loop while help
 Originally Posted by Shaggy Hiker
...
The problem you have with Randomize is that it re-seeds the random number generator with the system time down to the second. Two sequences with the same seed will be the same sequence. Therefore, by calling Randomize in a tight loop, you keep starting over with the same sequence. So, each time you get the first value from a sequence, then throw out the sequence and get a new sequence...which happens to be the exact same as the old sequence as long as the system time hasn't advanced by one second. So, if you get 5 the first time, then you will keep getting 5 over and over and over until the system time advances by one second
....
That isn't quite the way it works. You shouldn't call randomize over and over, but that is more because you mess up the distribution of the pseudo number generator, i.e. you will not get 16 million unique numbers in a row.
Calling Randomize with the same seed, will not generate the same sequence, unless you first reset the pseudo number generator by passing a -1 to the Rnd function.
To get a scenario that you describe, you would have to be calling Rnd(-1), before the call to Randomize, which would then pick the same starting point in the series for a given seed This is done to allowing you to repeat a "random" series for testing purposes.
And if you did call Rnd(-1) before calling Randomize(), it wouldn't repeat for a second, it is a much smaller time period than that. On my machine, I just tested, and the period of returning the same number is for a period of around 6 milliseconds. Of course, in a tight loop, I've generated the same random number 5 to 6 thousand times in a row in that 6 millisecond period.
If you don't have the Rnd(-1) in front of the Randomize(), then it won't start the sequence at the same spot, even if you use the same seed. I think it may be picking the same starting spot, i.e. the same series, but it doesn't reset the pseudo number generation so you continue picking the next number in the series (for 6ms apparently on my machine), but then the seed changes, and you now carry on picking but from a different spot in the overall series, which messes up the balanced distribution that pseudo random number generators are meant to provide.
If you try the following code, you will see it pick (most likely) 10 different numbers without repeating even with the Randomize() call in the loop.
If you uncomment the Rnd(-1) line, then you will be resetting the series so it starts at the beginning point the seed chooses.
All that said, the .Net Random object is superior in every way compared to the Rnd() function, so use of the Rnd() function should not be encourage, and in fact, discouraged.
Code:
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim r As Single
Dim r2 As Single
Dim count As Integer
Dim repeats As Integer
Dim sw As New Stopwatch
sw.Start()
Do While count < 10
' Rnd(-1)
Randomize()
r2 = Rnd()
If r2 <> r Then
r = r2
Debug.Print("{0} : {1}, ms: {2}, rndVal: {3}", Now.ToString, repeats.ToString, sw.ElapsedMilliseconds.ToString, r2.ToString)
sw.Restart()
count += 1
repeats = 0
Else
repeats += 1
End If
If repeats > 100000 Then Exit Do 'safety valve in case you decide to hardcode a seed, e.g. Randomize(5) above
Loop
End Sub
End Class
Hit F1, and look at the Randomize(Double) documuntation.
Note
To repeat sequences of random numbers, call Rnd with a negative argument immediately before using Randomize with a numeric argument. Using Randomize with the same value for Number does not repeat the previous sequence.
I guess based on that it doesn't have to be -1, any negative number should do.
But don't use it!
Last edited by passel; May 14th, 2020 at 09:58 PM.
"Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930
-
May 15th, 2020, 08:51 AM
#6
Re: Loop while help
If what you describe is the case, then I've either misremembered it, or things have changed. What I was reporting is how I found it to be working back when I used Randomize and Rnd. However, I don't believe I have done that since perhaps 1999, or even earlier. It has never made sense to me that the system time down to the second was being used, but at one point, that did indeed appear to be the case. Of course, that would have been on an early Pentium, either a 90, 100, or 120. Things are likely different from that, by now.
Also, I have never seen Rnd(-1), and wouldn't have thought it would work the way you are reporting. So, it seems like something has likely changed there, as well. However, that change may have been between VB5 and VB6. Back when I was looking at this....well, it really was that far back.
My usual boring signature: Nothing
 
-
May 15th, 2020, 12:43 PM
#7
Re: Loop while help
 Originally Posted by Shaggy Hiker
...
Also, I have never seen Rnd(-1), and wouldn't have thought it would work the way you are reporting. So, it seems like something has likely changed there, as well. However, that change may have been between VB5 and VB6. Back when I was looking at this....well, it really was that far back.
No, using Rnd with a negative number to reset was the way it was done, long before Visual Basic.
I pulled a couple of old references off the shelf, a hardcopy manaual for IBM BASIC 3.0 from 1984 (aka GWBasic from Microsoft before the QBasic era) and the Microsoft Professional Development System (PDS) version 7.0, from 1989, which was near the end of the QuickBasic compiler series (I'm pretty sure there was at least a 7.1), just before the first Visual Basic releases.
From the 1984 IBM BASIC manual first example page for the Rnd Function you have:
Code:
RND
Function
Example: In this example, the first horizontal line of results
shows three random numbers, generated using a positive x.
In line 40, a negative number is used to reseed the
random number generator. The random numbers
produced after this reseeding are in the second row
of results.
In line 80, the random number generator is reseeded
using the RANDOMIZE statement; in line 90 it is
reseeded again by calling RND with the same
negative value as in line 40. This cancels the
effect of the RANDOMIZE statement, as you can see; the
third line of results is identical to the second line.
In line 130, RDN is called with an argument of 0, so
the last number printed is the same as the preceding
number.
10 FOR I=1 TO 3
20 PRINT RND(I); ' x>0
30 NEXT I
40 PRINT: X=RND(-6) ' x<0
50 FOR I=1 TO 3
60 PRINT RND(I); ' x>0
70 NEXT I
80 RANDOMIZE 853 ' randomize
90 PRINT: X=RND(-6) ' x<0
100 FOR I = 1 TO 3
110 PRINT RND; ' same as x>0
120 NEXT I
130 PRINT: PRINT RND(0)
RUN
.6291626 .1948297 .6305799
.6818615 .4193624 .6215937
.6818615 .4193624 .6215937
.6215937
On the page before this example page, they described the use of 0, positive and negative values as seeds to the function, but I didn't replicate that here as we've discussed it a bit already. Bottom line, positive numbers are not seeds, and 0 prevents generating the next value in the series, it just returns the current seed, i.e. that last random number generated. Using a negative number is the only way to reseed the Rnd function, without using the Randomize statement.
In is interesting to note that in the RANDOMIZE function page, it says that the seed is a semi-required input, i.e. it isn't a syntax error to not provide a seed, but if you don't, then the user is prompted to enter a seed:
Random Number Seed (-32768 to 32767)?
The suggested method for not needing to prompt the user, and to allow some randomness, was to use the following statement (BASIC version 2.0 and later, which I assumed added the Timer function).
RANDOMIZE TIMER
Checking the PDS documentation, apparently this was still true, so using "Randomize Timer" was the standard incantation used at some point in the beginning of the program to avoid having a prompt show up for the user to input a value.
I guess when Visual BASIC 1.0 came out, especially since it was meant to be GUI based, not command line based, that they included using the Timer as the seed by default, if you didn't provide a Seed.
p.s. Based on the descriptions above, you can note some of the restrictions, which are still present through all versions of the Visual Basic Rnd function. Since the random value itself is based on the mantissa of a Single, the random series is limited to around 16 million unique values. But, regardless of what source you use as a seed (an Integer, Single or Double type is accepted), the seed gets converted to a 16-bit value (and I think it is the 15-bit value of the 16-bit value that is used), so there are only 32K places within the series of 16+million values that the series will start. Those two issues, the limit of 16 million numbers, and only 32k possible places that you can start in the series, is why it is not recommended to continue to use the old function.
Last edited by passel; May 15th, 2020 at 01:01 PM.
"Anyone can do any amount of work, provided it isn't the work he is supposed to be doing at that moment" Robert Benchley, 1930
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|