Seeding a pseudo-random number generator in C# - c#

I need a seed for an instance of C#'s Random class, and I read that most people use the current time's ticks counter for this. But that is a 64-bit value and the seed needs to be a 32-bit value. Now I thought that the GetHashCode() method, which returns an int, should provide a reasonably distributed value for its object and this may be used to avoid using only the lower 32-bits of the tick count. However, I couldn't find anything about the GetHashCode() of the Int64 datatype.
So, I know that it will not matter much, but will the following work as good as I think (I can't trial-and-error randomness), or maybe it works the same as using (int)DateTime.Now.Ticks as the seed? Or maybe it even works worse? Who can shed some light on this.
int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random r = new Random(seed);
Edit: Why I need a seed and don't just let the Random() constructor do the work? I need to send the seed to other clients which use the same seed for the same random sequence.

new Random() already uses the current time. It is equivalent to new Random(Environment.TickCount).
But this is an implementation detail and might change in future versions of .net
I'd recommend using new Random() and only provide a fixed seed if you want to get a reproducible sequence of pseudo random values.
Since you need a known seed just use Environment.TickCount just like MS does. And then transmit it to the other program instances as seed.
If you create multiple instances of Random in a short interval (could be 16ms) they can be seeded to the same value, and thus create the same pseudo-random sequence. But that's most likely not a problem here. This common pitfall is caused by windows updating the current time(DateTime.Now/.UtcNow) and the TickCount(Environment.TickCount) only every few milliseconds. The exact interval depends on the version of windows and on what other programs are running. Typical intervals where they don't change are 16ms or 1ms.

If you need to seed it with something other than the current time (in which case you can use the default constructor), you can use this:
Random random = new Random(Guid.NewGuid().GetHashCode());

I had a similar question , to select a random set of questions from a larger list of questions. But when I use the time as the seed it gives the same random number .
So here is my solution.
int TOTALQ = 7;
int NOOFQ = 5;
int[] selectedQuestion = new int[TOTALQ];
int[] askQuestion = new int[NOOFQ];
/* Genarae a random number 1 to TOTALQ
* - if that number in selectedQuestion array is not o
* - Fill askQuestion array with that number
* - remove that number from selectedQuestion
* - if not re-do that - - while - array is not full.
*/
for (int i = 0; i < TOTALQ; i++) // fill the array
selectedQuestion[i] = 1;
int question = 0;
int seed = 1;
while (question < NOOFQ)
{
DateTime now1 = new DateTime();
now1 = DateTime.Now;
Random rand = new Random(seed+now1.Millisecond);
int RandomQuestion = rand.Next(1, TOTALQ);
Response.Write("<br/> seed " + seed + " Random number " + RandomQuestion );
if (selectedQuestion[RandomQuestion] != 0)
{
selectedQuestion[RandomQuestion] = 0; // set that q =0 so not to select
askQuestion[question] = selectedQuestion[RandomQuestion];
Response.Write(". Question no " + question + " will be question " + RandomQuestion + " from list " );
question++;
}
seed++;
}

Related

System.Random not so random, why does this occur? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Random number generator only generating one random number
I've distilled the behavior observed in a larger system into this code sequence:
for (int i = 0; i < 100; i++)
{
Random globalRand = new Random(0x3039 + i);
globalRand.Next();
globalRand.Next();
int newSeed = globalRand.Next();
Random rand = new Random(newSeed);
int value = rand.Next(1, 511);
Console.WriteLine(value);
}
Running this from Visual Studio 2012 targeting .NET 4.5 will output either 316 or 315. Extending this beyond 100 iterations and you'll see the value slowly decrement (314, 313...) but it still isn't what I'd imagine anyone would consider "random".
EDIT
I am aware that there are several questions on StackOverflow already that ask why their random numbers aren't random. However, those questions have issues regarding one of a) not passing in a seed (or passing in the same seed) to their Random object instance or b) doing something like NextInt(0, 1) and not realizing that the second parameter is an exclusive bound. Neither of those issues are true for this question.
It's a pseudo random generator which basically creates a long (infinite) list of numbers. The list is deterministic but the order can in most practical scenarios be treated as random. The order is however determined by the seed.
The most random behaviour you can achieve (without fancy pants tricks that are hard to get right all the time) is to reuse the same object over and over.
If you change your code to the below you have a more random behaviour
Random globalRand = new Random();
for (int i = 0; i < 100; i++)
{
globalRand.Next();
globalRand.Next();
int newSeed = globalRand.Next();
Random rand = new Random(newSeed);
int value = rand.Next(1, 511);
Console.WriteLine(value);
}
The reason is the math behind pseudo random generators basically just creates an infinite list of numbers.
The distribution of these numbers are almost random but the order in which they come are not. Computers are deterministic and as such incapable of producing true random numbers (without aid) so to circumvent this math geniuses have produced functions capable of producing these lists of numbers, that have a lot of radnomness about them but where the seed is determining the order.
Given the same seed the function always produces the same order. Given two seeds close to each order (where close can be a property of which function is used) the list will be almost the same for the first several numbers in the list but will eventually be very different.
Using the first random number to generate the second. Doesnt make it any more "Random". As suggested try this.
Also as suggested no need to generate the random object inside the loop.
Random globalRand = new Random();
for (int i = 0; i < 100; i++)
{
int value = globalRand.Next(1, 511);
Console.WriteLine(value);
}
I believe the Random() is time based so if your process is running really fast you will get the same answer if you keep creating new instances of your Random() in your loop. Try creatining the Random() outside of the loop and just use the .Next() to get your answer like:
Random rand = new Random();
for (int i = 0; i < 100; i++)
{
int value = rand.Next();
Console.WriteLine(value);
}
Without parameters Random c'tor takes the current date and time as the seed - and you can generally execute a fair amount of code before the internal timer works out that the current date and time has changed. Therefore you are using the same seed repeatedly - and getting the same results repeatedly.
Source : http://csharpindepth.com/Articles/Chapter12/Random.aspx

Why do I keep getting two of same random values in this code? [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#?
I have the following code:
int a;
int aa;
Random aRand = new Random();
Random aaRand = new Random();
a = aRand.Next(20);
aa = aaRand.Next(20);
//if (a == aa)
{
Console.WriteLine(a + " " + aa);
Console.ReadLine();
}
I'm assuming that aRand and aaRand would be two different values, but that's not the case. What am I doing wrong? I'm assuming that aRand and aaRand will not always be the same, but they keep coming out the same all the time.
Thanks
This is explicitly covered in the docs for Random():
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.
Why are you creating two different Random variables? You could use just one:
int a;
int aa;
Random aRand = new Random();
a = aRand.Next(20);
aa = aRand.Next(20);
//if (a == aa)
{
Console.WriteLine(a + " " + aa);
Console.ReadLine();
}
Edit:
"The random number generation starts from a seed value. If the same seed is used repeatedly, the same series of numbers is generated. One way to produce different sequences is to make the seed value time-dependent, thereby producing a different series with each new instance of Random. By default, the parameterless constructor of the Random class uses the system clock to generate its seed value, while its parameterized constructor can take an Int32 value based on the number of ticks in the current time. "
from http://msdn.microsoft.com/en-us/library/system.random.aspx
You only need one instance of Random() - just call .Next() twice.
int a;
int aa;
Random aRand = new Random();
a = aRand.Next(20);
aa = aRand.Next(20);
You should never have more than One Random variable in your entire application. Get rid of the second
Random aaRand = new Random();
It looks like the two instances are using the same seed.
the seed determines all the values that will be generated and in which order. If you create 200 instances of Random with the same seed, they'll all give you the same output.
Create a single Instance when your app starts and reuse it.

Random number generator always picks the same value when run inside a loop

The problem with the code is, when I try to generate a number, if the spin is equal 1 it generates values inside range (1,2,3) if if try to use the loop to sum random values inside the same range the random number gerated is always the same while in loop,
example, if I run the loop with:
spind3 = 4 the values go from 4, 8, 12
spind3 = 5 the values go from 5, 10, 15
That means the first time the RandomNumber generates a value inside loop, it never change until the loop completes.
if (toggled3.Checked)
{
if (spind3.Value != 1)
{
for (int i = 1; i <= spind3.Value; i++)
{
diceCalc[1] += RandomNumber(1, 4);
}
}
else
diceCalc[1] = RandomNumber(1, 4);
}
You are probably creating a new Random object inside RandomNumber method. The default constructor for Random uses the system time as a seed. If you create multiple Random objects in a tight loop the time probably won't have changed between each call so they will all be initialized with the same seed.
To fix your code you should only create one Random object and reuse it.
From the documentation:
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. For more information, see the Random(Int32) constructor.
The problem is that you are creating random generators too close in time. The random generator constructor uses the current time to seed the generator, and when you create them too close in time they will all be seeded using the same time.
Create one random generator and use in the loop:
Random rnd = new Random();
for (int i = 1; i <= spind3.Value; i++) {
diceCalc[1] += rnd.Next(1, 4);
}
You need to initialize your Random object, then call Next() inside your loop.
i.e.
if (toggled3.Checked)
{
// initialize your total and the random number generator
int diceTotal = 0;
Random rand = new Random();
for (int i = 0; i < spind3.Value; i++)
{
// add the next random number between 1 and 3
diceTotal += rand.Next(1, 4);
}
}
You can use Random(seed) constructor.
Random rand = new Random(Guid.NewGuid().GetHashCode());
One trick is to manually create the seed by adding DateTime.Now.Ticks to the variable i:
Random r = new Random((int)DateTime.Now.Ticks + i);

more than 1 sequence of random numbers c#, linq

i was using this code to generate a random sequence of numbers:
var sequence = Enumerable.Range(0, 9).OrderBy(n => n * n * (new Random()).Next());
everything was ok till i need more than one sequence, in this code i call the routine 10 times, and the results are my problem, all the sequence are equal.
int i = 0;
while (i<10)
{
Console.Write("{0}:",i);
var sequence = Enumerable.Range(0, 9).OrderBy(n => n * n * (new Random()).Next());
sequence.ToList().ForEach(x=> Console.Write(x));
i++;
Console.WriteLine();
}
Can someone give me a hint of how actually generate different sequences? hopefully using LINQ
The problem is that you're creating a new instance of Random on each iteration. Each instance will be taking its initial seed from the current time, which changes relatively infrequently compared to how often your delegate is getting executed. You could create a single instance of Random and use it repeatedly. See my article on randomness for more details.
However, I would also suggest that you use a Fisher-Yates shuffle instead of OrderBy in order to shuffle the values (there are plenty of examples on Stack Overflow, such as this one)... although it looks like you're trying to bias the randomness somewhat. If you could give more details as to exactly what you're trying to do, we may be able to help more.
You are creating 10 instances of Random in quick succession, and pulling the first pseudo-random number from each of them. I'm not surprised they're all the same.
Try this:
Random r = new Random();
var sequence = Enumerable.Range(0, 9).OrderBy(n => n * n * r.Next());
In my code I use this static method I wrote many years ago, and it still shows good randomization:
using System.Security.Cryptography;
...
public static int GenerateRandomInt(int from, int to)
{
byte[] salt = new byte[4];
RandomNumberGenerator rng = RandomNumberGenerator.Create();
rng.GetBytes(salt);
int num = 0;
for (int i = 0; i < 4; i++)
{
num += salt[i];
}
return num % (to + 1 - from) + from;
}
Can't explain this example in detail, I need to bring myself back in time to remember, but I don't care ;)

Array 2 method random generated number

For a part of a program i need the following 2 methods.
The first method listed will generated a random number.
where the 2nd method will "call" this method to fill the array.
The array has a max. number of elements defefined on 100 (and all the random generated numbers should be between 1-100).
The problem is i never get random numbers generated. (either i get 100 x the same value, 3 random numbers divided over the 100 max. elements of the array, or the same value 100 times all over again).
The problem should be in the first method, but i cannot seem to figure out the problem.
Been staring at this for quite some time now...
The problem should be with the return, cause it DOES create random generated numbers. But how do i return the generated value every time? (the int method has to be called with the 3 parameters).
private int ValidNumber(int[] T, int X, int Range)
{
for (byte I = 0; I < T.Lenght; I++)
{
Random RndInt = new Random();
X = RndInt.Next(1, Range+1);
}
return X;
}/*ValidNumber*/
public void FillArray(int[] T, int Range)
{
for (byte I = 0; I < T.Length; I++)
{
T[I] = ValidNumber(T, I, Range);
}
}/*FillArray*/
Console code:
public void ExecuteProgram()
{
ClsBereken Ber = new ClsBereken();
//const byte Range = 100;
const int Max = 100;
int[] T = new int[Max];
Ber.FillArray(T, Max);
DisplayArray(T);
}/*ExecuteProgram*/
private void DisplayArray(int[] T)
{
for (byte i = 0; i < T.Length; i++)
{
Console.Write("{0,4} ", T[i]);
}
Console.WriteLine();
}/*DisplayArray*/
Any help alot appreciated.
Kind Regards.
Re-use the Random instance. NOTE I've edited this to show passing the Random instance down, but I'm really not sure what ValidNumber is trying to do - it looks like it is juts burning up CPU cycles? I would suggest you can remove ValidNumber completely (and just use the next value from the Random in FillArray), but presumably you are trying to do something here - I'm just not sure what!
private int ValidNumber(int[] T, int X, int Range, Random random)
{
for (byte I = 0; I < T.Lenght; I++)
{
X = random.Next(1, Range+1);
}
return X;
}/*ValidNumber*/
public void FillArray(int[] T, int Range)
{
Random random = new Random();
for (byte I = 0; I < T.Length; I++)
{
T[I] = ValidNumber(T, I, Range, random);
}
}/*FillArray*/
When you create a Random, it is "seeded" using the system clock, but this is rounded heavily. If you create lots of Random in a tight loop, they all get the same "seed", so they all create the same next number.
If necessary you could move the Random further out (if you have other loops), or make it static (but if you do that you need to worry about synchronization too).
The problem is that you are reinitializing rndint over and over.
take the line:
Random RndInt = new Random();
and move it in front of the loop and see if that fixes it.
When you initialize a random object, it is assigned a seed (probably based on the time), and that seed is used to generate a series of seemingly random values. However, if you plug in the same seed to two random objects, you will get the same series of random numbers.
So, what is happening in your code is you are initializing a new random object with a seed, and then asking for the first random number in its series. Then, you are initializing another random object (even though it is assigned to the same name, it is a new object) and it is getting the same seed, and you are again asking for the first random number in the series. So naturally, you are getting the same random number over and over.
You are continuously creating an new Random object. I'm afraid this is seeded (randomized) by the timestamp of creation. Since this is really fast and happens multiple times, the seed is the same, and so is the result of the call RndInt.Next(1, Range+1);.
By the way, even though not incorrect, it's not a common practice in c#.net to start with a capital letter on names of local variables and parameters.
Any random number generation algorithm* is not truly random; it is simply a deterministic algorithm that has been specifically designed to output numbers that resemble randomness. (See Pseudorandom number generator.) Since the algorithm is deterministic, its output is completely dependent upon a starting "seed" value.
The Random class in .NET has two constructors: one which takes an integer seed, and another which takes no parameters. This one bases its seed off the current time.
From this information perhaps you can guess why creating a new Random instance for every value in your array results in the entire array being filled with the same number: every time you construct a Random object within a very small time frame, it will have the same seed value, which means it will generate identical output to another Random object constructed within the same time frame.
As Marc Gravell has already indicated, you should be using only a single Random instance to generate a sequence of random numbers.
*Well, almost any. I believe there are hardware implementations of random number generators that factor in random noise (taken from the surrounding environment) and may therefore be considered "truly" random. Whether you believe these are actually random
depends on your personal definition of "random" and whether or not you believe that we live in a deterministic universe.
You can pass Random() a seed but if you send it the same seed number you will get the same results. The way you are using it
Random rnd = new Random();
Is using an auto-generated seed based on time. But you may not get seemingly random results if you don't at least sleep for a second. (Source http://msdn.microsoft.com/en-us/library/system.random(VS.71).aspx)
As everyone has mentioned here already your biggest issue is the fact you keep recreating the random object each iteration.

Categories