How much does new Random() depends on time? [duplicate] - c#

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 5 years ago.
Yesterday I wrote my first answer at Programming Puzzles & Code Golf. The question said this:
Given an input string S, print S followed by a non-empty separator
in the following way:
Step 1: S has a 1/2 chance of being printed, and a 1/2 chance for the program to terminate.
Step 2: S has a 2/3 chance of being printed, and a 1/3 chance for the program to terminate.
Step 3: S has a 3/4 chance of being printed, and a 1/4 chance for the program to terminate.
…
Step n: S has a n/(n+1) chance of being printed, and a 1/(n+1) chance for the program to terminate.
So I went and wrote this code (ungolfed):
Action<string> g = s =>
{
var r = new Random();
for (var i = 2; r.Next(i++) > 0;)
Console.Write(s + " ");
};
This code works fine, but then someone said that I could save a few bytes creating the r variable inline, like this:
Action<string> g = s =>
{
for (var i = 2; new Random().Next(i++) > 0;)
Console.Write(s + " ");
};
I tried but when I executed the code, it always went in one of two possibilities:
Either the program halted before printing anything (the first call to Next() returns 0), or
The program never stops (the calls to Next() never return 0).
When I reverted the code to my original proposal, the program stopped more randomly as expected by the OP.
I know that the new Random() constructor depends on time, but how much? If I add a Sleep() call, the code behaviour starts to seem really random (but not much, the strings returned are still longer than the ones returned by the initial code):
Action<string> g = s =>
{
for (var i = 2; new Random().Next(i++) > 0; Thread.Sleep(1))
Console.Write(s + " ");
};
If I increment the sleep time to 10 ms, now the code really behaves like the original one.
So why is this? How much does the Random class depends on time? How exactly does the Random class seeds the number generator when calling the empty constructor?
Note: I know that creating a single Random object is the best practice, I just wanted to know a bit more than what the MSDN says:
The default seed value is derived from the system clock and has finite resolution.
What is that "finite resolution" the Random class default constructor uses as seed? How much time should we separate the construction of two Random objects to get different sequences? How much would those two different sequences differ when creating the Random instances too close in time?

What is that "finite resolution" the Random class default constructor uses as seed?
It uses Environment.TickCount which has a resolution of one millisecond.
How much time should we separate the construction of two Random objects to get different sequences?
As per the previous section, by at least one millisecond - or manually feed another seed to the constructor each time (or, well, reuse the same generator?)
How much would those two different sequences differ when creating the Random instances too close in time?
Matt Moss did a nice visualization in his Random Headaches from System.Random blog post:
Each row of the bitmap represents five first generated numbers with that seed (without preserving generated order):
As you can see, numbers are being selected from distinct but related sequences. As MSDN on Random says, "The chosen numbers... are sufficiently random for practical purposes."

Related

What is the refresh rate of the random() method in C# [duplicate]

This question already has answers here:
Random number generator only generating one random number
(15 answers)
Closed 7 years ago.
I am going to generate 100 random numbers in a for loop. The only problem is that since the random() method is timer-based, it will generate the same numbers 3-4 times in a row.
I can solve this problem by including a threat.sleep() method in my loop. Therefor i want to know the exact refresh rate of the random() method so that i can match the threat.sleep() method and not get delayed more than necessary.
Here is my code:
for (int i; i <= 100; i += 1)
{
Random rndNum = new Random();
Console.WriteLine(rndNum.Next(1, 100));
Thread.Sleep(X); //I want to know the best value of X (as less delay as possible)
}
Thanks a bunch
/HamMan4Ever
I've never heard or read that the Random class is timer-based. You may have heard that it is seeded by the system time, but after that each call to Next will return a randomish number typically different from the previous. Typically when you see non-random data coming from a Random, it's because you're creating a new random on each iteration through a loop, as you are in the code you shared. Since each is seeded from the system clock and you're creating several very quickly, you see repeated patterns. Create your Random outside the loop to make this problem go away.
It is equal to the refresh rate of the system clock as it uses the time as a seed. But for your job, you should keep the Random instance outside the loop.
Random rndNum = new Random();
for (int i; i <= 100; i += 1)
{
Console.WriteLine(rndNum.Next(1, 100));
}
Since it uses the time as a seed, it uses it only ones and will generate random numbers even if you call it multiple times at the same time as long as you use the same instance.

The output is differ when debugging vs Step Into solution

I have a very strange problem that I never been in touch with in my entire life.
This is what I been up to:
I have programmed a game that involves you going to throw two dices and the sum of the two dices should be seven for you to win.
This is how the interface is built:
The textbox1 shows the value of first thrown dice.
The textbox2 shows the value of second thrown dice.
The textbox3 shows the sum of the both dices.
The button1 throws the dices.
This is the problem:
When i Debugg (F5) the application in Visual Studio 2013 Ultimate
the textboxes gets the exactly same value all the time. This is wrong, it shouldn't act like this.
When i Step Into (F11) the application/code the textboxes gets
different values, just as it should be, this is right, this is how the program should act.
Is there anyone that can help with this problem, i think that I have just missed a very small but a obvious thing that I have missed but I really can't find anything, I'm actually out of ideas!
Attachments
Here is all the files, I hope it will help you, the program is written in Swedish but I don't think that makes any problem, if it do, I can translate the whole solution to English.
The whole Solution: Throw_Dices.zip
The Code: Big picture on three screens of the code
From MSDN:
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
In your Kasta.cs, create a static instance of Random instead of multiple ones.
public class Tarning
{
private static Random ran = new Random();
int slump;
public int Kasta()
{
//Random ran = new Random();
slump = ran.Next(1, 6);
return slump;
}
}
Another possibility would be to create a seed manually. For instance like
public int Kasta()
{
byte[] seed = new byte[4];
new RNGCryptoServiceProvider().GetBytes(seed);
int seedInt = BitConverter.ToInt32(seed, 0);
Random ran = new Random(seedInt);
slump = ran.Next(1, 6);
return slump;
}
Instead of creating two Dice (Tarning ?)
Create one and roll it twice.
Or create both on start up, Or perhaps have a class that holds 2 dice.
and throw them again.
You should also google random and seeding, what's happening is from the same seed value, you get the same sequence of random numbers. Debugging is introducing enough of a delay between the new Random calls, that the seed (based on the clock) has changed between the two calls.
PS your button1Click handler
should set the three textbox values, not trigger textbox changed events which then set them. Imagine if you wanted to reuse your code, you'd have to create a UI to do it.
A better way would be to have a class that held two (or n) dice with a Roll method and a property that returned the result. Then you could reuse it without worrying about when and how.

Loop runs too fast?

I have a loop (below) that loops N number of times based on user input. the loop, calls a method that creates a random string of text for an insert into a database. I want the loop to call this method before it executes the query, so every insert into the database has a different random string of characters.
What seems to be happening, is that the loop runs too quickly, and the random string is inserted about 50 times because the dynamic string variable doesn't get updated quick enough. However, if I throw in a Thread.Sleep(50), the code executes perfectly.
I don't like the thread.sleep option because I don't know exactly how long it needs to sleep, and this time will add up if we start running a few hundred thousand transactions. does anyone have a good solution to ensuring that the method executes completely before it moves on?
for (int i = 0; i < nLoop; i++)
{
rnd.RndName();
query.CommandText = "insert into XXX (col";
query.ExecuteNonQuery();
}
What seems to be happening, is that the loop runs too quickly, and the random string is inserted about 50 times because the dynamic string variable doesn't get updated quick enough .
The instructions inside your loop will be executed one after the other.
Unless rnd.RndName() fires up a separate thread (in which case, show that code) it will complete before the following two statements execute.
If the name is not changing, the problem lies elsewhere.
however, if i throw in a thread.sleep(50), the code executes perfectly.
Nothing in the code you have shown would be sensitive to a thread sleep. If that is having some effect, the issue lies in how rnd.RndName() is implemented. Perhaps you are creating a new instance of Random each time (as suggested in the comment by #rynah)? If so, the instance is initialized using the system time. That would cause the behavior you observe.
The Random class does not really generate random numbers. It generates a deterministic series of numbers for a given seed value. If you seed to the current number of ticks (which I believe Random does), creating many Random instances in quick succession will cause them all to have the same seed, and therefore to produce the exact same sequence of numbers.

Creating a true random [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why does it appear that my random number generator isn't random in C#?
How can I generate truly (not pseudo) random numbers with C#?
I've created a dice game where the dice is based on a percentile, 1-100.
public static void Roll()
{
Random rand = new Random((int)DateTime.Now.Ticks);
return rand.Next(1, 100);
}
But I don't feel like it's a real random based on current time.
If I do
for (int i = 0; i < 5; i++)
{
Console.WriteLine("#" + i + " " + Roll());
}
They would all be the same values, because the DateTime.Now.Ticks didn't change, it seeded the same number.
I was thinking I could generate a new random seed if the seed was the same due to the current time, but it doesn't feel like an honest "re-roll"
What should I do to try and replicate a close to real/honest dice roll? Should I use the RNGCryptoServiceProvider class to generate rolls instead?
DateTime.Now.Ticks only has a resolution of approximately 16ms, so if you create a Random with that overload multiple times within a 16ms "slot" they will all be seeded with the same value and therefore you will get the same sequence.
Initialize your Random outside your loop so that a single Random sequence is produced, rather than creating it each time within the loop which could result in Randoms being seeded with the same value and so produce the same sequence.
Update
My previous point that the default constructor initialized Random with CPU ticks was incorrect, the default constructor actually uses Environment.TickCount which is:
A 32-bit signed integer containing the amount of time in milliseconds that has passed since the last time the computer was started.
Which still has a low resolution. If you make multiple instances of Random in quick succession, they can easily be created within the same time slot and therefore have the same seed value, and create the same sequence. Create a single instance of Random and use that.
Update
Further to your comments, if you wish to generate a random sequence across multiple threads, please see the following Jon Skeet article which discusses a thread-safe wrapper:
https://codeblog.jonskeet.uk/2009/11/04/revisiting-randomness
Pseudo-random number generators like Random should only be seeded once, so:
private static Random _rand = new Random();
public static int Roll()
{
return _rand.Next(1, 100);
}
(Note I made the return value int rather than void; the Roll function as quoted in the question results in a syntax error.)
But your title says "Creating a true random". Random won't do that for you, it's a pseudo-random number generator, meaning it's deterministic, just hard to predict if you don't know the seed. Usually that's good enough for most purposes, but if you need real randomness, you need an entropy source. http://random.org is one popular one.
You should create your Random class only once outside your Roll function and seed it with a unique value.
You are recreating your Random each time you call Roll which causes the 'not random numbers'.
Should I use the RNGCryptoServiceProvider class to generate rolls instead?
If this is a serious game with money at stake then: Yes.
I'm assuming that you are calling the Roll() method so quickly that Now.Ticks is the same?
The simplest way to get around this would be rather than to create a new Random() instance each time you call Roll() create a static variable to hold a single instance of Random().
The usual way to use random number generators is to seed them once, save them and call on them repeatedly throughout your programme. As long as you seed from a suitable value at the start, you should get acceptable randomness - assuming the generator you're using is using a function returning things which are suitably random for your purposes. So, save your Random instance outside the Roll() function, seed it the first time it's used, then just call Next() on it each time you need another number.
When you get right down to it, there's no such thing as true random number generation on a computer, only pseudorandom sequences based on a seed. However, humans are terrible at identifying randomness, so it's usually okay.

Random numbers for dice game [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
random string generation - two generated one after another give same results
I am writing a simple dice game for windows phone 7, that involves rolling two dice at the same time. Here is my Dice Roll Code:
private int DiceRoll()
{
int result;
Random rnd = new Random();
result = rnd.Next(1, 7);
return result;
}
I then have this code that rolls the dice when a button is clicked:
private void roll_Click(object sender, RoutedEventArgs e)
{
roll1 = DiceRoll();
roll2 = DiceRoll();}
My problem is that both die get the same result.
Any idea how I can get a rolling algorithm that will usually return different results, but occasionally return the same?
The default seed for Random is based on the current time. To quote the documentation,
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.
That is exactly what you should do: create one instance of Random and use it to generate all your random numbers.
You need to keep one Random object around and reuse it; every time you create a new Random object, you effectively reset the sequence of numbers to begin in the same place. Store the Random object as a member variable someplace. You'll also want to seed it with a different value each time you run the program -- for example, a value based on the system clock time.
The clear majority of 'random number' tools I've seen fail badly if you allocate two or more random objects in a single application. You're allocating a new Random object for every invocation, and each time they are going to be seeded with something pretty weak, and maybe even identical seeds.
So, generate a single Random object and use it over the life of your application.

Categories

Resources