C# System.Random needs sleep to work [duplicate] - c#

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 8 years ago.
for (int i = 1; i <= 55; i++ )
{
System.Random myRandom = new System.Random();
//int myInt; 3 lines just alternate method
//myInt = myRandom.Next();
//System.Console.WriteLine(myInt);
System.Console.WriteLine(myRandom.Next());
Thread.Sleep(15); // if less, trouble
}
I kept getting multiples of the same number, up to twenty at a time, instead of each consecutive number being different. For some reason I added the sleep statement and it works if the value is 15 or greater. In fact, if you increment the sleep argument value, you can 'select' how many consecutive repeated numbers you get. Setting a range made no difference. Is the loop faster than the random number generator? This is not serious, I am working through the book "Essential C# 5.0". I looked at least fifty "random" questions, but none covered this phenomena. The three commented lines are a different way to do the same thing, I did not execute both in the same build.

The problem lies in this line:
System.Random myRandom = new System.Random();
It should be outside the for-loop. Why? Because it generates a random seed based on the timing information, and as you create them one after another, they each get the same seed. When you make the thread sleep in-between the iterations, the time changes enough so that the next Random gets a different seed value.
Try this instead:
System.Random myRandom = new System.Random();
for(int i = 1; i <= 55; i++)
{
// Here be the rest of the code
}
Now, the Random object is created just once, getting its seed value just once.

Related

Not jumping into code while not debugging [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 3 years ago.
for (int i = 1; i < 10; i++)
{
number = randomNumber();
if (!straightLine.Contains(number))
{
straightLine.Add(number);
}
}
public static int randomNumber()
{
Random random = new Random();
return random.Next(1, 100);
}
when I debug it works fine but when I run the program it gets 1 random number and that's it. so the problem is that the random Number method is only called once (when I don't debug then it calls it every time)
what can I do?
germi's answer is slightly misleading as it implies that any repeated instantiation of a new Random will produce the same sequence of values. This isn't quite correct, because your debug code works as you expect.
The documentation for Random says that the Random number generator is seeded from the system clock if you dont pass a seed value. https://learn.microsoft.com/en-us/dotnet/api/system.random.-ctor?view=netframework-4.8
The reason it works in debug is that debugging code is very slow (you're literally taking hundreds of milliseconds to step through the code a line at a time) and the clock has time to change in between runs of the loop.
When your code is run at full speed it runs so quickly that the system clock simply won't have changed to a new milliseconds value, so your repeated making of a new Random will result in it being seeded with the same value from the clock
If you were to insert some delay in the code such as Thread.Sleep(1000) in the loop then it would work. If you were to run the loop a million times it would take long enough to work through that the clock would eventually change - a million iterations might take long enough for a small handful of values to come out of the Random
The recommendation for a solution is sound though; make one new Random somewhere outside of the loop and then repeatedly call it. You could also seed the Random with something that is unique each time (like the value of i), though you should bear in mind that providing a particular seed will guarantee that the same random number comes out of it when you call Next. In some contexts this is useful, because you might want a situation where you can provide a certain value and then see the same sequence of random numbers emerge. The main thing to be mindful of is that by default the Random starts it's sequence based on the clock; two different computers with different time settings can theoretically produce the same random numbers if their clocks are reading the same at the moment the Random is created.
Repeatedly instantiating a new Random instance will lead to the same number being generated, since the seed will be the same.
The solution is to have one instance of Random in the class that generates the values:
var random = new Random();
for (int i = 1; i < 10; i++)
{
number = random.Next(1,100);
if (!straightLine.Contains(number))
{
straightLine.Add(number);
}
}
Note that this behavior only exists in .NET Framework, .NET Core will produce different values even across multiple Random instances created in quick succession.

Class For generating Random Code

I wrote this class to generate a random code, it shouldn't create any two repetitive number.
I want to know, in this code, how much it possible that we have collision?
public string MyRandom()
{
Random r = new Random();
int x = r.Next(1000);//Max range
PersianCalendar pc = new PersianCalendar();
string _myrandom = pc.GetMonth(DateTime.Now).ToString() + pc.GetDayOfMonth(DateTime.Now).ToString() + pc.GetHour(DateTime.Now).ToString() + pc.GetMinute(DateTime.Now).ToString() + pc.GetSecond(DateTime.Now).ToString() + pc.GetMilliseconds(DateTime.Now).ToString() + x.ToString();
return _myrandom;
}
If we do
List<string> s = new List<string>();
for(int i = 0; i < 100; i++)
{
s.Add(MyRandom());
}
Why?
When random class is created in a loop, you can get duplicate random numbers. More Info
Solution:
Create Random instance outside loop.
It is safer to use more stronger methods such as RNGCryptoServiceProvider which you can find several samples of its usage. Generally, pure random generation is not possible is very high concurrency loads, but reduce its probability to a reasonable amount.
Well first, because you are using the date in the way that you are, then there is only one possible millisecond per year where the _myrandom string could possibly be repeated.
Within that millisecond each year, the odds of hitting a random string you have already generated are down to the variable x, and related directly to how many other random strings you have made in that millisecond (and the previous milliseconds of each previous year). If, for example, you were to have made 10 random strings last year in that millisecond and 4 the year before, the chances of duplication this year are 14:999, which is a chance of about 1.4%.
Of course, if you make 1000 strings per millisecond, the chance of duplication is 100%.
In fact, the chances of duplication are slightly higher, due to the fact that the C# Random number generator doesn't produce a true random number. It's a pseudo-random number, so the chances of a collision are higher.
I see that you've written: "this generator is using for naming photos which uploaded in my application" in the comments above, which makes it unlikely that you'll be making 1000+ names per millisecond. Generally, whenever you are using a random number generator in this way, it's a good idea to just put in some error checking in 1 of two ways:
1. offensive or 2. defensive.
Offensive would be waiting for the error (two identical file names) to happen and then dealing with it (maybe running your random generator again until the error isn't thrown). Defensive would be to check all of the filenames in the file, or keep a list of them all, to check that your new filename isn't the same before you even try to save it. This is more watertight (because you aren't relying on an error to be thrown) but far more computationally expensive.

Random.Next() Digits always gives the same output every runtime

I know there are lots of questions about random in here but they didn't help me at all, they are about generating same numbers in a single runtime, and mine isn't
So here is my code.
Random rnd = new Random(0);
for (int c = 0; c < arraySize; c++)
data[c] = rnd.Next();
if i run it for the first time.
the element of rnd.Next() would be 1559595546
next output would be 1755192844
and so on,
if i close the program and re run it,
the same set of numbers would be generated
data[0] = 1559595546
data[1] = 1755192844
and so on,
Why is that so? isnt it should generate different set of numbers every time i close the program and run it?
please help me understand this.
No, you're providing a fixed seed of 0. Therefore the output is always the same. Take a read of the documentation for the constructor overload that you are using:
http://msdn.microsoft.com/en-us/library/ctssatww%28v=vs.110%29.aspx
paying particular attention to the following statement:
Providing an identical seed value to different Random objects causes each instance to produce identical sequences of random numbers.
Perhaps you should:
var rnd = new Random(); //no seed
Thsi is because you have provide Seed 0 like
Random = new Random(0); //0 is Seed
If you remove it then it will generate different random numbers as you required.

Why Random makes same selection always? [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 9 years ago.
When I executes the following code I'm getting the same color selected always.
static void Main(string[] args)
{
string[] Colors = new string[10] { "Red", "Yellow", "Green", "Blue", "Purple", "White", "violet", "orange", "indigo", "blue" };
for (int i = 0; i < 13; i++)
{
Random rnd = new Random();
int code = rnd.Next(0, 9);
string Color = Colors[code];
Console.WriteLine(Color);
}
Console.ReadLine();
}
But if ` Random rnd = new Random();' is created outside the loop, then the result is unique. If the loop executes in faster rate then the output will be the same. Suppose I do some Database insert operation in the for loop the result will be a different one (a random one)(step by step execution using break points will also result random selection).
Is it really impossible to supply different seeds for such a small duration?
Random uses current time as a seed. When you create it in loop, it happens so fast that time stays the same for every creation. So seed is the same, and values, generated by Random will be the same too.
Try make random object a static member:
private static Random rnd = new Random();
This prevents building several random objects with a same seed (current time), and prevents producing a same sequence of numbers.
Your loop initializes a new instance of Random with the same seed (current time) upon each iteration. Each instance contains a sequence of various random numbers. The code uses the first number from the sequence, and after the iteration is finished the random object is thrown away, and a new Random object is instantiated. Since the code has been run quite fast, the next random object is created at the same time as the previous one, therefore it has the same seed as that one. The new object contains a sequence of various numbers, but the sequence is the same as the previous one (i.e., they have a same first number, second number, and so forth). Again the code uses the first number from the very same sequence, which results in repetitive numbers.
If you make the Random object a static member, the random sequence is created once, and the code will use the next number (not always the first number) of that sequence, hence you will iterate through the sequence of various random numbers.
If you don't want to make the random object a static member, try to feed its constructor a unique seed. You can make use of your loop variable for this purpose.
If you don't provide a seed, Random will use Environment.TickCount for a seed. In a short loop like this, it's entirely possible that the the whole loop is executed in one tick. So the seed is the same every time, hence your "random" number is, too.
Just use the same random object for the entire loop.
Random is not random in computer programming ;) You can make it "more" random by including a seed or by having a static object containing the random :)
you need to keep the same random object for the reason below:
Pseudo-random numbers are chosen with equal probability from a finite set of numbers. The chosen numbers are not completely random because a definite mathematical algorithm is used to select them, but they are sufficiently random for practical purposes.
The random number generation starts from a seed value. If the same seed is used repeatedly, the same series of numbers is generated.
http://msdn.microsoft.com/en-gb/library/system.random.aspx

Die Roller with user selecting number of sides

I'm new to programming and I'm trying to build a die roller game in C#.
The program asks the user for the number of sides and then rolls a dice with a random number.
I have the following pseudocode:
ask user for the number of sides.
roll the die with a random number with max range being the number of sides.
tell the user the number rolled
My question is how do I roll the dice with generating a random number in range specified by the user?
The System.Random class is commonly used to generate casual random numbers.
It has an overload of a method called Next which generates a random integer that is greater than or equal to 0 and strictly less than the passed integer argument.
Thus if the user chooses an n-sided die, and you have an instance of Random r,
r.Next(n) + 1
will generate a random integer between 1 and n inclusive.
It is good practice to create a single instance of Random and reuse it, because if you create several instances close together they will all generate the same numbers.
Random random = new Random();
int randomNumber = random.Next(1, userInput);
One thing for you to know though is the random function isn't exactly random, its random but in the same random order everytime.. I'll let you look on your favourite search engine for seeding ;)
To get a Random integer between 0 and 100 with 100 not included:
Random random = new Random();
int randomNumber = random.Next(0, 100);
System.Random, specifically System.Random.Next(Int32, Int32) should get you started.
Random.Next(Int32, Int32)
Returns a random number within a specified range.
public int RollDice(int iNoSides)
{
var rand = new Random();
return rand.Next(iNoSides) + 1
}
A simple google of random number c# would of got you more or less this exact code.
EDIT
You have the link to the MSDN documentation from other answers and comments, I know your new to programming but the best way to learn is to try as hard as you can to get something. If you get to a state where your mind can't function any more, posting your attempt with your question on Stack will make people generally a lot happier that they are genuinely helping somebody that is stuck
EDIT 2
Following #Rawling's comment, I realised that the overload of the method states that Next(n) returns a Non-negative number less than the specified maximum.

Categories