views:

96

answers:

5

Hi, the following code is fairly straight forward - it fills a design surface with randomnly selected pixels - nothing special (ignore the XXXXXXX's in the 2nd method for now).

private void PaintBackground()
{
    Random rnd = new Random();

    Bitmap b = new Bitmap(this.Width, this.Height);
    for (int vertical = 0; vertical < this.Height; vertical++)
    {
        for (int horizontal = 0; horizontal < this.Width; horizontal++)
        {
            Color randomColour = GetRandomColor(rnd);
            b.SetPixel(horizontal, vertical, randomColour);
        }
    }

    Graphics g = this.CreateGraphics();
    g.DrawImage(b, new Point(0, 0));
}

public Color GetRandomColor(Random rnd)
{
    XXXXXXXXXXXXXXXX

    byte r = Convert.ToByte(rnd.Next(0, 255));
    byte g = Convert.ToByte(rnd.Next(0, 255));
    byte b = Convert.ToByte(rnd.Next(0, 255));

    return Color.FromArgb(255, r, g, b);
}

The question i have is this...

if you replace the XXXXXXXXX with "Random rnd = new Random();" the test pattern completely changes into horizontal bars of the same colour, and is therefore not random.

Come someone explain to me why this is?

As far as I can tell the only difference in the second attempt is that the GetRandomColour method creates and uses a new instance of the Random class but I don't see how that makes horizontal bars..

+3  A: 

Your application runs so fast that the seed the PRNG is being initialized with, stays the same throughout the entire loop.

Thus it is not truly random, hence the name Pseudo Random Number Generator.

leppie
Wouldnt there be slight variations in the horizontal bars though? they're almost perfectly aligned
Grant
Nope, the RNG is initialized with the same seed, so it will generate the same results. Your vision just sees this as lines.
leppie
+6  A: 

From MSDN:

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. However, because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers. The following example illustrates that two Random objects that are instantiated in close succession generate an identical series of random numbers.

So given the same seed the Random instance will produce the same sequence of numbers. And in your example due to the finite resolution of the system clock, the Random instances were created using the same tick count as seed, resulting in the same sequence.

The consecutive calls to GetRandomColor() are executed within one time slice of the system clock. To test this, try slowing the method down with Thread.Sleep(1). You should see different colors being generated.

Yannick M.
I was too slow, deleted my post and gave you +1
jdehaan
+1  A: 

Random when created have a default seed zero. Recreating it in that function will always give the same number. Create it in constructor and than reuse to get different random numbers.

affan
Wrong! The seed is based on something like tickcount, else you would end up with a real crappy random class.
leppie
You right i was wrong. I remember that when i was implementing a Particle swarm optimizer and had almost same problem. But since sequences were almost identical for each particle i concluded that it must be same. Thanks for the info.
affan
+1  A: 

Randoms aren't really random. They're "Psuedo-random". All you're really doing (from the machine standpoint) is generating the same random at the origination point over and over again. What you really need to do is either pass the constructor a "seed" or have a higher scoped random that you can call the Next() method.

Joel Etherton
so in attempt #2 - by creating a new instance and asking it for next(0, 255) it will be the same return value everytime? that seems hard to believe.. ?
Grant
Yes, because they all have the same start point. And the randomness algorithm isn't random at all. Like the article says, it's "psuedo-random". It has a definite algorithm so given the same start point, same seed, you'll achieve the same result every time.
Joel Etherton
A: 

See this article. (Kidding)

Repo Man