views:

112

answers:

2

Hey guys,

I've got a class that represents a coin, which can be flipped with the Coin.Flip() method. Flip() uses random.Next(2); to get either a 0 or a 1 representing heads or tails. This works good.. sort of.

For the program, I need to have 2 coins, which I make, lets say coin1 and coin2.

coin2 always needs to be flipped straight after coin1, which I can do with:

coin1.Flip();
coin2.Flip();

That should work, right?

Well it doesn't! Every time I run those two lines of code, both coins end up with the same values as each other!

The face value is stored in face inside the Coin class, which is defined like this:

private int face;

I don't see anything wrong with what I've done, yet every single time I run the code, they end up identical.

Oh, also, random is defined in the Coin class as well like so:

private Random random = new Random();

Thanks for your help!

EDIT: Here's Flip(), it works now that random is static though.

    public void Flip() {
        face = random.Next(2);
    }
+5  A: 

Random number generators need a seed value. RNG's with an identical seed will produce the same stream of random numbers.

By default, System.Random uses the current time as the seed. If you create two instances almost immediately after each other, they will both likely have the same time value, and therefore will produce the same random number sequence.

You can move the Random to a static member so that all Coin's share the same RNG, but be aware that System.Random is not documented as threadsafe so you can't use multiple Coin's on different threads without some synchronization.

Michael
Thanks mate, I was thinking about this right after I posted. Will give it a shot.
Azz
That's heaps better. Thanks again!
Azz
It might be a good idea to create an overload to your Coin() that allows you to pass in a random stream as well, and the default constructor takes the static random stream. This way you can resolve any synchronization issues by creating seperate rng's for each thread
erash
I'm not great with all of the terminology, but the way I read your comment, it's like this: Use the overloaded version whenever I want a new RNG, and use the standard constructor when I want to use the already created RNG. I'm not multi-threading, so I don't think I need to do this, just trying to understand though. Thanks!
Azz
+3  A: 

My guess is that you probably want to redefine your random variable, at the class level, as:

private static Random random = new Random();

This will make every call to Flip() use the same generator, and not reseed constantly. If you're creating the Random instance every call, and call two times very close together, you may get the same seed, and hence the same values.

Reed Copsey