Visual Basic Randomize() vs New Random - vb.net

It seems that Randomize() & Rnd() aren't used anymore.
Instead people make something like:
Dim rng as New Random()
Dim randomNo as Integer = rng.Next(10) ' this is a random number between 0 and 10.
Dim anotherRandomNo as Integer = rng.Next(10) ' a different random number.
Could someone tell me why this is considered "better" in most circumstances?

There are a few reasons.
Random has much greater functionality .. Have a look here
Also and more importantly the old Randomize is built into the instantiation of a Random object. By default, Rnd without randomize always started with the same seed number. If you didn't use randomize at the start of your program, each time it ran, it would generate the same sequence of numbers.
Finally, internally the Random object generates numbers in a different way with a better spread of randomness.

Related

Vb Guessing Game Random generator broken

In my code,I have now realised I have to use the New Random function, my code was working before with the Randomize and then the numbers but now it comes up with loads of errors and wont even let me run the program. I think it is only a small error but I just need some help to get the final bit going
Heres the code and thanks for any help :)
I cannot get the code to work with the randomly generated number and I have to use the New Random function I cannot use randomize() Does anybody know how to help here is the code.
Dim timestook As Int32 = 1
Dim usersguess As Integer
Dim value = New Random(0 - 19)
Console.WriteLine("You have to guess this number. It is between 1 and 20. Good Luck !")
usersguess = Console.ReadLine()
'keep looping until they get the right value
While usersguess <> value
'now check how it compares to the random value
If usersguess < value Then
timestook = timestook + 1
Console.WriteLine("You're too low. Go higher ")
ElseIf usersguess > value Then
Console.WriteLine("You're too high. Go Lower.")
timestook = timestook + 1
End If
'If they are wrong the code will run again,after telling the user if they are too high or too low.
usersguess = Console.ReadLine()
End While
' Console.WriteLine("You're correct. Well Done")
If usersguess = value Then
Console.WriteLine("You took,{0}", timestook)
End If
Console.ReadLine()
End Sub
You'll want to do some googling on how to use random numbers. Your problem is that you aren't creating a Random object to handle the random number generation.
Here's how you can fix your code:
Dim randNumGen As New Random() 'Create Random object
Dim value As Integer = randNumGen.Next(0, 20) 'set value equal to a new random number between 0-19
Please note that this code could be further refactored for readability and simplicity (like changing timestook = timestook + 1 to timestook += 1 and selecting better variable names like numberOfGuesses as opposed to timestook, etc.
The expression New Random(0-19) does not do at all what you think it does, name it does NOT return an integer. Instead, it creates an instance of a Random object, which is a type that knows how to create new random values. The 0-19 part of the expression is the seed for the Random object's constructor, and is the same as just passing the value -19.
This looks like it's either homework or personal practice, so I feel like you will be better served in this case with a separate example using the Random type for reference than you would if I fixed the code sample in the question for you:
Dim rnd As New Random()
For i As Integer = 0 To 10
Console.WriteLine(rnd.Next(0, 20))
Next i
It's also worth mentioning here that you typically only want one Random object for your entire program, or at least only one Random object for each logical part of your program. Creating new Random objects resets the seeds, and for best results you want to follow the same seed on subsequent calls to the same instance for a while.

Random from listbox

there has been many posts about this but nobody seems to have my problem.
I have a list box with letters a-z (line for each letter)
using
Dim rancon As New Random
Dim rc As Integer = ListBox1.Items.Count
Label5.Text = lcon.Items.Item(rancon.Next(rc)).ToString
all it is doing is chosing randomly, 1 of the first 7 or 8 characters.
can anyone advise?
I assume that you expect that the random always chooses a different item in the ListBox. Therefore you have to reuse the same Random instance since the default constructor derives the seed(which is used to initialize the pseudorandom number generator) from the current system time.
If you call this code very fast(for example in a loop), the seed will always be the same. Hence you get repeating numbers/items.
To avoid this you could make the Random a field in the class:
Private rancon As New Random
Public Sub YourMethod()
Dim rc As Integer = ListBox1.Items.Count
Label5.Text = ListBox1.Items(rancon.Next(rc)).ToString()
End Sub
MSDN:
The default seed value is derived from the system clock and has finite
resolution. As a result, different Random objects that are created in
close succession by a call to the default constructor will have
identical default seed values and, therefore, will produce identical
sets of random numbers. This problem can be avoided by using a single
Random object to generate all random numbers. You can also work around
it by modifying the seed value returned by the system clock and then
explicitly providing this new seed value to the Random(Int32)
constructor.
Note that i've also used ListBox1.Items instead of lcon.Items in case that was a typo.

Getting Duplicate Random Numbers

I'm doing basic random number generation using this Shared Function:
Public Shared Function RandomNumber(ByVal MaxNumber As Integer, Optional ByVal MinNumber As Integer = 0) As Integer
'initialize random number generator
Dim r As New Random(Date.Now.Ticks And &HFFFF)
If MinNumber > MaxNumber Then
Dim t As Integer = MinNumber
MinNumber = MaxNumber
MaxNumber = t
End If
Return r.Next(MinNumber, MaxNumber)
End Function
Called like this: dim x as integer = Random(2100000000)
Very simple, and the seed value comes straight from a MS example.
HERE'S THE PROBLEM: I'm getting duplicate numbers on occasion, but always created at times that are usually at least 5 or 10 minutes apart. I can see if I was calling the function multiple times per second or millisecond, because that'd kind of "breaks" the seed. But these are showing up at extended time spans. What else could be causing this?
Duplicate seed issue?
It might be better defining r as static so that it is initialised once when first invoked. Refer to this answer Random integer in VB.NET
The Random constructor takes an Integer as its parameter which is 32-bits. As spencer7593 said, with only 16 bits, you're repeating the sequence every 6.5ms. Try:
Dim r As New Random(Date.Now.Ticks And &HFFFFFFFF)
However, this will do the same thing:
Dim r As New Random()
Better yet, don't create a new Random object each time:
Private Static r As New Random()
Public Shared Function RandomNumber(MaxNumber As Integer, Optional MinNumber As Integer = 0) As Integer
...
Return r.Next(MinNumber, MaxNumber)
End Function
Q: What else could be causing this?
A: It could be happening purely by random. Random numbers are just that: random. At any point in time, whether its seconds or hours away from another point in time, its just as likely for a number to appear as any other number. There is no guarantee that a number won't be repeated.
On the other hand, it looks like your seed value is only on the order of 16 bits. And that's like a total of 65,536 possibilities. There's 10,000 ticks in a millisecond, so ever 6.5 milliseconds you have the possibility of reusing the same seed.
It's not at all clear whether the VB Random is using some other kind of entropy beyond that seed or not. (But gathering entropy for inclusion would slow down the initialization, so it may not be, as a performance consideration.)
According the docs, creating two Random objects using the same seed value results in Random objects that create duplicate sequences of unique numbers.
http://msdn.microsoft.com/en-us/library/ctssatww.aspx
I think that answers the question why it is happening.
I guess the next question is why do you need to instantiate a new Random object? If you need multiple objects, then instantiating several of them, but making sure you are using a different seed value for each one would be one approach.
But before you go there, I recommend you consider using just one Random. Calls to get random numbers can be serviced from an existing Random, rather than creating a new one every time you need a random number.
Try it another way:
Public Function RandomNumber2(ByVal MaxNumber As Integer, Optional ByVal MinNumber As Integer = 0) As Integer
' Initialize the random-number generator.
Randomize()
' Generate random value between MaxNumber and MinNumber.
Return CInt(Int((MaxNumber * Rnd()) + MinNumber))
End Function
See Randomize Function (Visual Basic) for more details. Hope this helps.

Using Randomize() before Rnd() in VB.NET

I have previously been told that I should always use Randomize() before I use Rnd() in a VB.NET application. Yet, it always seems to work fine without it. What does adding Randomize() do for me in this case?
It doesn't appear to affect my application in the least.
In Visual Basic, Rnd() uses a mathematical operation to produce the next "random" number. Because the actual operation is known, given a specific value, you can predict the next value. However, given an arbitray start value the numbers have good distribution - these are "pseudo-random" numbers.
To keep Rnd() from startng at a predictable number (and hence giving the same sequence of "random" numbers every time), Randomize() should be called to use the machine clock to set the initial value (called a seed).
(In the .NET world, I'd use System.Random instead if you can.)
Randomize() initializes the first seed of Rnd(). If you won't use it - VB.NET will use the default seed number.
Randomize will set the seed to something time related, like the system uptime or the system date. So the function Rand() will show different values every time the app is executed. However, I highly recommend you to use the System.Random class instead of VisualBasic Rand(). No need to call any randomize() function
Here are some example code, this will generate six random integers from the lower to upper bounds:
Dim randObj As New Random( seed )
Dim j As Integer
For j = 0 To 5
Console.Write( "{0,11} ", randObj.Next( lower, upper ) )
Next j
Console.WriteLine( )

Same random number generated when run in test Fixture setup

I am trying to generate a random number during testing using NUnit, but it keeps generating the same number. I am using the following function for this purpose.
dim dCount As Integer = Math.Floor((High - Low + 1) * Rnd() + Low)
dim divName As String = "abc" & dCount
Any idea why it is doing this?
Regards,
Sam
Presumably you're executing many tests in quick succession. I don't know exactly what Rnd() does in VB, but it sounds like it's got the typical "new RNG per call" problem.
Create a single instance of Random and use it repeatedly. Note that your maths can be replaced by a simple:
dim dCount as Integer = myRandom.Next(Low, High+1)
One caveat - Random isn't thread-safe. If you need to generate random numbers from different threads, either use locking or thread statics.
On another point: using random numbers will make your unit tests non-deterministic. Are you sure you have to? Sometimes it's appropriate, but not often IME.
Dim dCount As Integer = between(low, high)
Dim divName As String = "abc" & dCount
Dim myRandom As New Random
Private Function between(ByVal low As Integer, ByVal high As Integer) As Integer
between = myRandom.Next(low, high + 1)
End Function