1

I am still new to C# and I am trying to build a short program that simulates flipping a coin X number of times:

        // Declarations
        int headCount = 0;
        int tailCount = 0;

        // Main Program Logic
        Console.WriteLine("Press enter to begin");
        Console.ReadLine();
        for (int x = 1; x <= 25; x++)
        {
            Random rnd = new Random();
            int flip = rnd.Next(1, 3);
            if (flip == 1)
            {
                Console.WriteLine("Heads");
                headCount++;
            }
            else
            {
                Console.WriteLine("Tails");
                tailCount++;
            }
        }
        Console.WriteLine("Heads came up {0} times.", headCount);
        Console.WriteLine("Tails came up {0} times.", tailCount);
        if (headCount > tailCount)
        {
            Console.WriteLine("Heads wins.");
        }
        else
        {
            Console.WriteLine("Tails wins.");
        }

        // END OF DOCUMENT
        Console.ReadLine();
    }

Now, I am confident that my code is solid, however, I encounter a problem when I run the program. In the code above, the idea is that each time the for loop is executed that a new random number (either 1 or 2) is generated. In reality, 9 times out of ten, it generates one number the first time and then uses that number for the rest of the loop's executions.

Everyone once in a while, the results are about 50/50 (what you would statistically expect), but usually it is just the same result repeated 25 times.

Note that I declare the flip variable inside the loop. I have moved it back and forth from in the loop and just before the loop and the changes seem to not have any effect.

Am I doing something wrong or does C# like to throw out statistical anomalies?

  • Everyone gave the right answer, here is some extra reading on Random numbers: http://msdn.microsoft.com/en-us/library/system.random.aspx#remarksToggle – ermagana Oct 14 '13 at 22:54
  • If you need better randomness consider using the RNGCryptoServiceProvider as I detail below. – Kevin Oct 14 '13 at 23:03
  • The fastest way to solve your problem is to generate a big array of random numbers before using it in the loop. Then generate a random array start_index numer (or not if you plan to use the array from 0 index). Use the start_index number to get the first generated random number form the array when program it enters the loop. Then get (index+x) on each loop itration. Also check, and reset the start_index if it reaches the end of the array with random numbers. – TomeeNS Aug 28 '16 at 21:26

4 Answers4

7

The reason is because you keep calling new Random(). Instead you should be constructing this outside your loop and THEN call .next(int,int)

 Random rnd = new Random();
 for (int x = 1; x <= 25; x++)
 {
        int flip = rnd.Next(1, 3);
        //do stuff
 }
JNYRanger
  • 6,829
  • 12
  • 53
  • 81
4

Instantiate your random number generator outside of the loop so it will be able to properly generate random numbers.

The reason for this is that the seed is based mainly off of the cpu clock. Keep in mind that computers can only generate "psuedo random" numbers. To do that, they use the seed and some math. If the seed used is from the same time (since the code in the loop executes in nanoseconds) each random number is the same.

When used outside of the loop, the seed will provide a basis for creating a different random number every time one is called for.

Travis J
  • 81,153
  • 41
  • 202
  • 273
2
Random rnd = new Random();

This is your problem. You are reinitializing the generator every time through the loop. Since you aren't providing a seed, the default constructor uses the current time accurate to milliseconds as the seed. Since your loop is running quite quickly, this number is the same for most iterations of your loop, resulting in you generating the same number repetitively.

The solution: Move it outside the loop =)

Further reading: Pseudo-Random Number Generators

Tyler Lee
  • 2,736
  • 13
  • 24
0

You need to initialize your random number generator outside of your loop!

        Random rnd = new Random();
        Console.WriteLine("Press enter to begin");
        Console.ReadLine();
        for (int x = 1; x <= 25; x++)

EDIT: Actually I was able to get good distributions from your code by just moving the random initializer up above the Console.ReadLine()

EDIT 2: If you want a MUCH better random number consider using a RNGCryptoServiceProvider.

RNGCryptoServiceProvider rnd = new RNGCryptoServiceProvider();
var randomByte = new byte[1];
rnd.GetBytes(randomByte);

Granted it's not quite as friendly to use (since it gives you random bytes rather than integers) as Random but it gives much better randomness. However this random number generator is good enough to use for Cryptography where as Random should not be used for Cryptography.

Kevin
  • 4,586
  • 23
  • 35
  • What do you meant by `give it a somewhat random seed` ? To generate a random number you need to give a random seed? Funny! – Sriram Sakthivel Oct 14 '13 at 22:51
  • Random is actually a function that returns numbers that seem random. However... it is still just a function. So every time you start with the same seed value you will get the same string of "random" numbers out of it. – Kevin Oct 14 '13 at 22:56
  • I know that already, but to get a random number you need a random seed? how'll you generate the seed then? with another random class with a random seed? – Sriram Sakthivel Oct 14 '13 at 23:13
  • @SriramSakthivel often you use something based on the time. In this case with Random() using the default constructor it uses a time dependent seed value. – Kevin Oct 15 '13 at 14:24
  • That also I know, IIRC it uses `Environment.TickCount`. what's your point? – Sriram Sakthivel Oct 15 '13 at 14:30
  • @SriramSakthivel I was just answering your question and you come back with I know that... what's your point? funny. – Kevin Oct 15 '13 at 14:32
  • Still you haven't answered my question, you're answering something else which I already know. My question is *What do you meant by give it a somewhat random seed ? To generate a random number you need to give a random seed?* – Sriram Sakthivel Oct 15 '13 at 14:34
  • @SriramSakthivel From my comment above "Often you use something based on time" - this is how you generate a somewhat random seed to start with. "Random() using the default constructor uses a time depenedent seed value" - means you can let Random use its default time dependent seed. Either way the algorithm has to start with a somewhat random seed whether you pass one into Random() or let it generate one from the time. – Kevin Oct 15 '13 at 14:39