Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Random not that random [duplicate]

Tags:

c#

.net

random

I am using Random to generate a sequence of random number. I am constructing the random object just once and then inside the loop generating the random values (300 of them). The problem is that once I get all the values and do a sort on them I realize that some of them are equal and/or sequential: I am generating numbers from 0 to 50000.

This is my script:

Random rnd = new Random();
for (int n=0; n < 300; n++)
{
    int RndNumber = rnd.Next(0, 50000);
    System.Threading.Thread.Sleep(3);
}

Can someone have a clue on why this is happening, and how can I improve this to make it more random?

like image 691
Terrence Avatar asked Feb 01 '11 04:02

Terrence


People also ask

Why is random not really random?

Since a truly random number needs to be completely unpredictable, it can never depend on deterministic input. If you have an algorithm which takes pre-determined input and uses it to produce a pseudo-random number, you can duplicate this process at will just as long as you know the input and algorithm.

Is Excel random really random?

And for most folks, the built-in random generator for Excel works fine for their needs. However, Excel uses what is called a pseudorandom number generator, in this case, the Mersenne Twister algorithm. What that means is that, technically speaking, the numbers that Excel's RAND functions generate aren't truly random.


2 Answers

So this is the birthday paradox*. When you draw 300 numbers from 50000 the approximate probability that at least two of them are equal is

p(300) = 1 - exp(-300 * 300 / (2 * 50000))
       = 0.59

(I could work out the exact probability but I'm lazy!.)

So, chances are more likely than not that you'll have a collision. Sequential is even more likely (now you don't need a collision, you just need n - 1 and n or n and n + 1 to be hit for some n).

Random is fickle.

*: In case you're not familiar with it, it says that if you have twenty-three people in a room, it is more likely than not that at least two people in the room share the same birthday.

!: Okay, I worked it out. It's 0.5953830515549951746819986449....

like image 116
jason Avatar answered Oct 05 '22 13:10

jason


Research:

If you use the constructor without parameters new Random() the seed is depending on the current servertime.

Random(): "Initializes a new instance of the Random class, using a time-dependent" http://msdn.microsoft.com/en-us/library/system.random.aspx

So, if I try it like this:

for(int i = 0; i < 1000; i++)
{
   Random ran = new Random();
   Console.WriteLine(ran.Next(50001));
}

I only get 3 different numbers about 300 times within a thousand calls! Not that random...

Setting the seed in the constructor new Random(0) returns a fix serie of numbers.

e.g. new Random(0).Next(50) always! returns 36. Try it yourself, if you don't trust me;

What we need for "real" random numbers is a changing seed, that's independent of time.

I'm using Hashcode of changing values:

e.g. Guid.NewGuid().GetHashCode() or DateTime.Now.GetHashCode()


Result:

Random ran = new Random(Guid.NewGuid().GetHashCode());
for(int i = 0; i < 1000; i++)
{       
   Console.WriteLine(ran.Next(50001));
}

or (for better performance):

for(int i = 0; i < 1000; i++)
{
     int val = Guid.NewGuid().GetHashCode() % 50001;
     val = val > 0 ? val : -val;
     Console.WriteLine(val);
}

PS: The maximum of the Next(max)-method is always max - 1;

-> ran.Next(11) can return 0,1,2,...,8,9,10. Not 11!

like image 21
Bahamut Avatar answered Oct 05 '22 11:10

Bahamut