Random Number in C#, Be careful of some of the samples you find.

I recently came across this code on the internet for generating a random number with C#.

   1: private static int RandomNumber(int min, int max)
   2: {
   3:    Random random = new Random();
   4:    return random.Next(min, max);
   5: }

The problem with this code is that for a novice developer (and maybe even some advance developers) it can be misleading and in some instance will not work.  Take for instance the following code…

 

The issue with this is not immediately obvious, but if you remember one thing about the Random object in C# is that when you do not pass it any parameters is uses a time based seed.  In addition, if you use the same seed for an new instance the same numbers will be generated, thus they number really are not random. The same is also true for the Random.Next function, if called within the same time the same number as previous will be generated.  So in the case of the function above, the for loop can go through the loop 4-5 times within a millisecond, so that means the same “random” number will be generated.  So this function really does not generate a real random ID (since the same characters are repeated 4-5 times).

   1: public static string GenerateID(int MinSize, int MaxSize)
   2: {
   3:    string stRefID = String.Empty;
   4:    int iChosenMaxSize = RandomNumber(MinSize, MaxSize);
   5:  
   6:    for (int x = 1; x <= iChosenMaxSize; x++)
   7:    {
   8:       int iCharType = RandomNumber(1, 3);
   9:  
  10:       switch (iCharType) 
  11:       {
  12:          case 1:
  13:          {
  14:             stRefID += char.ConvertFromUtf32(RandomNumber(48, 57));
  15:             break;
  16:          }
  17:          case 2:
  18:          {
  19:             stRefID += char.ConvertFromUtf32(RandomNumber(65, 90));
  20:             break;
  21:          }
  22:          case 3:
  23:          {
  24:             stRefID += char.ConvertFromUtf32(RandomNumber(97, 122));
  25:             break;
  26:          }
  27:       }
  28:    }
  29:  
  30:    return stRefID; 
  31: }

So the code that does what is really needed cannot use the RandomNumber function that I found on the internet.  Below is how the the function above can be written not using the RandomNumber function to do what is expected.

   1: public static string GenerateID(int MinSize, int MaxSize)
   2: {
   3:    string stRefID = String.Empty;
   4:    Random random = new Random();
   5:    int iChosenMaxSize = random.Next(MinSize, MaxSize); 
   6:  
   7:    for (int x = 1; x <= iChosenMaxSize; x++)
   8:    {
   9:       int iCharType = random.Next(1, 3);
  10:  
  11:       switch (iCharType)
  12:       {
  13:          case 1:
  14:          {
  15:             stRefID += char.ConvertFromUtf32(random.Next(48, 57));
  16:             break;
  17:          }
  18:          case 2:
  19:          {
  20:             stRefID += char.ConvertFromUtf32(random.Next(65, 90));
  21:             break;
  22:          }
  23:          case 3:
  24:          {
  25:             stRefID += char.ConvertFromUtf32(random.Next(97, 122));
  26:             break;
  27:          }
  28:       }
  29:  
  30:       System.Threading.Thread.Sleep(1);
  31:    }
  32:  
  33:    return stRefID; 
  34: }

The 2 keys to the update function are:

1) The Random() object is only instantiated once so the seed is only set once.

2) The addition of the Thread.Sleep(1) call between each of the time through the loop.  This makes sure that when the Next function is called the time has changed so that the number generated will not be the same as previously generated.

This is not a knock on the sample code I found, since it would work in certain instances.  But just a warning to be aware that when downloading code samples (even if they get good reviews), might not work in the situation that you need it for and IMO need to be tested even more than code you wrote yourself.

Share This Post

Published Sunday, March 15, 2009 11:04 PM by smehaffie
Filed under: ,

Comments

# re: Random Number in C#, Be careful of some of the samples you find.

Monday, March 16, 2009 5:13 AM by Prakash Punnoor

Are you sure you want to Sleep in the loop? As you are reusing your random instance, this is unnecessary and only killing performance (esp due to forced context switches). I suggest calling the Sleep before returning - and maybe even trying to prevent that by using a stopwatch and measuring how long your loop took. Then if the time taken is below a certain threashold, call Sleep.

# re: Random Number in C#, Be careful of some of the samples you find.

Monday, March 16, 2009 10:59 AM by Dave G

I'd suggest looking/blogging about RNGCryptoServiceProvider's strong random number provider, instead of the method you suggested.

Also, your example is not good as far as reusable, functional programming goes .. i.e. Keep the RandomNumber() function, and put the Sleep call in the function.  Functions are there to make maintenance and life!) easier.

# Random Number in C#, Be careful of some of the samples you find. - Shawn's Technical Blog

Monday, March 16, 2009 11:16 AM by DotNetShoutout

Thank you for submitting this cool story - Trackback from DotNetShoutout

# re: Random Number in C#, Be careful of some of the samples you find.

Monday, March 16, 2009 11:33 PM by Mital Kakaiya

I believe that your post is misleading for other developers. If you do not provide a valid seed value to 'Random' class, it reads 'System.Environment.TickCount' internally (Reflector), which generates a same random number (becuase seed value is not different in a loop).

To avoid this issue, you need to provide a valid seed as follow:

// ------------ Code Sample ------------

System.Random random = new System.Random();

int nextRandom = random.Next(1, 1000);

System.Console.WriteLine(nextRandom);

for (int index = 0; index < 100; index++)

{

random = new System.Random(nextRandom);

nextRandom = random.Next(1, 1000);

System.Console.WriteLine(nextRandom);

}

System.Console.ReadKey();

NOTE: Do not use Thread.Sleep(1) to get different 'Tick' value for seeding, as it's bad performance application.

# re: Random Number in C#, Be careful of some of the samples you find.

Tuesday, March 17, 2009 12:43 AM by Raj

Consider using System.Security.Cryptography.RNGCryptoServiceProvider

weblogs.asp.net/.../238389.aspx

msdn.microsoft.com/.../system.security.cryptography.rngcryptoserviceprovider(vs.71).aspx

# re: Random Number in C#, Be careful of some of the samples you find.

Friday, April 17, 2009 11:49 PM by smehaffie

1) I will definitely look into the System.Security.Cryptography.RNGCryptoServiceProvider.

2) As for using the sleep, as written it only adds 8 milliseconds to each call to GenerateID.  For what this function will be used for at this time this is acceptable.  IMO, whether or not the performance hit is an issue or not depends on the usage and in this case we have decided using the sleep is not a big deal in this case.

# re: Random Number in C#, Be careful of some of the samples you find.

Saturday, April 18, 2009 2:38 AM by smehaffie

Mital Kakaiya, actually you statement "... which generates a same random number (because seed value is not different in a loop)." is misleading.

You are correct that that if you do not provide a seed value the random function does use the TickCount.  But within a loop you will get duplicate random number for iteration within the same millisecond, but once the millisecond changes the random number returned by Random.Next also changes.

In the code I posted (w/o sleep) and in your code the random number generated would not be the same for every time through the loop.  The random number would be the same but only for the number of iterations through the loop that is in the same millisecond.  (In most cases that is every 4-5 random numbers). For example, without the Sleep(1) I would get the Generated ID's that looked like the following:

1111SSSDBBBB7777hhhh

777DDDFkkkk5555

By adding the sleep(1) it garantees that each Random.Next call is made in the next tick (millisecond), thus I then get Generated ID's that look like this.

S4gyf690kHuDda

724RdGTjn876UhfdemK

D28fHY86jmkA54BGadE

Very big difference and definitely generating random ID's as expected. As stated in previous post, for what it is used for the 8 millisecond performance hit per call is acceptable.

# re: Random Number in C#, Be careful of some of the samples you find.

Wednesday, November 11, 2009 10:29 PM by Colin

Next() called on the same instance of System.Random will return new random numbers each call, even within the same millisecond. You do not need to Sleep().

Your earlier problems were related to seeding, but if you are using the same instance, you don't run into them.

# re: Random Number in C#, Be careful of some of the samples you find.

Thursday, May 13, 2010 3:51 PM by Dude

Dude, I love you! I actually have read that misleading article even though I used just random.nextDouble(). Random kept giving the same number for every object and I didn't understand why but you pointed out that System.Threading.Thred.Sleep. I had to give a little bit higher number for it as a parameter to fill my needs but your article was precious.

# re: Random Number in C#, Be careful of some of the samples you find.

Tuesday, February 01, 2011 3:51 PM by Hassan

:O

use of for from 0 to 100?

no, i made a class which generate some value for example from 1 to 8 and then put it in an array ...

newly i come up with application, which i need 2x of any index so i done new randomMaker(min,max);

and its same, so u say i make a for...

if i make a for inside class RandomMaker{ ....FOR(1..100){}.......) it still start from 1 for both...

and nothing gonna happen

# re: Random Number in C#, Be careful of some of the samples you find.

Saturday, February 12, 2011 9:19 AM by Dustin

This uses Date Ticks and uses the last 5 digit in the 17 digit value. (These are the digits that change extremely quickly and are the best way to seed the Random function, other than more advanced "noise" techniques)

Heres my function for Randomizing numbers.

public int RandomInt(int intMin, int intMax)

{

   long timestamp = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).Ticks);

   int seed = Convert.ToInt32(Convert.ToString(timestamp).Substring(11));

   Random r = new Random(seed);

   return r.Next(intMin, intMax);

}

# re: Random Number in C#, Be careful of some of the samples you find.

Wednesday, May 25, 2011 11:30 PM by weblogs.asp.net

Random number in c be careful of some of the samples you find.. He-he-he :)

# re: Random Number in C#, Be careful of some of the samples you find.

Friday, June 17, 2011 3:35 PM by masoud

check the following codes:

internal static class ppp

   {

       public static Int32 pp = 10;

   }

   class Random

   {

       public float uniform(float a, float b)

       {

           float o, temp;

           System.Random r = new System.Random(ppp.pp);

           temp=(float)r.NextDouble();

           ppp.pp = r.Next(1, 100);

           o = (b - a) * temp + a;

           return o;

       }

# re: Random Number in C#, Be careful of some of the samples you find.

Monday, July 04, 2011 3:32 AM by in need of help

hi can somebody please help me, i have to generate 2 random numbers. and have to keep on generating 2 numbers until the 2 numbers are the same. i then have to calculate how many times i had to generate so that the 2 numbers are the same.

fanx alot

# re: Random Number in C#, Be careful of some of the samples you find.

Monday, July 04, 2011 3:33 AM by in need of help

hi can somebody please help me, i have to generate 2 random numbers. and have to keep on generating 2 numbers until the 2 numbers are the same. i then have to calculate how many times i had to generate so that the 2 numbers are the same.

fanx alot

# re: Random Number in C#, Be careful of some of the samples you find.

Friday, December 16, 2011 11:02 PM by Anthony Sycamore

How about this:

public class RandomGlobal

{

 private static Random r;

 public static Random Random

 {

   get

   {

     if (r == null)

       r = new Random();

     return r;

   }

 }

}

Call e.g. RandomGlobal.Random.NextDouble()

# re: Random Number in C#, Be careful of some of the samples you find.

Sunday, February 05, 2012 1:04 PM by Mike D

@Mital Kakaiya    your code is not correct here.

What you are doing is giving users code that, unless used appropriately, will generate the same number.

c# has a big issue here, and the best way to go is use alternative class. If you have to use Random, the Sleep is about the only way to guarantee randomnes.

Please be sure of what you say before posting code. Incorrect codee just gets circulated and wastes users time.

Congrats to smehaffie on seeing the issues of c# Random.

Leave a Comment

(required) 
(required) 
(optional)
(required)