Brendan Tompkins

Sponsors

The Lounge

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
This is like, so random! Some Randomness from System.Random

If you want a true random number generator, you will want to look beyond System.Random, to the RNGCryptoServiceProvider in the .NET Framework. In fact, there's a good article here that shows how to get a strong password using this method.

But how do you ensure randomness using the System.Random class? 

Creating truly random numbers can be tricky, especially if you need to create a series of random numbers repeatedly.  It’s easy to misunderstand, in fact, you really can’t even trust the code samples from MSDN Documentation for the System.Random Constructor.  Here’s the crux of this issue.

If your application requires different random number sequences, invoke this constructor repeatedly with different seed values. One way to produce a unique seed value is to make it time-dependent. For example, derive the seed value from the system clock.

However, if your application runs on a fast computer the system clock might not have time to change between invocations of this constructor; the seed value might be the same for different instances of Random. In that case, apply an algorithm to differentiate the seed value in each invocation.

The documentation goes on to show some code that supposedly will generate some random numbers, by calling Thread.Sleep(1).  However, this won’t work!  It may work in their example, but in fact, the only reason I think this works in the MSDN Documentation example is by chance!  They just happen to be using enough cpu cycles in a loop (and thus getting a new, unique timer tick) to make the example work! Consider the following code:

 

    static internal string RandomString(int size)

    {

      Thread.Sleep(1);

      Random rand = new System.Random();

 

      StringBuilder builder = new StringBuilder();

 

      for(int i=0; i<size; i++)

      {

        char ch = Convert.ToChar(Convert.ToInt32(26 * rand.NextDouble() + 65)) ;

        if(ch < 0x5B || ch > 0x60) builder.Append(ch);

      }

 

      return builder.ToString();

    }

 

If you run this test below, it fails (and not just because of the by chance occurance of two truly random strings actually being equal), but because Thread.Sleep(1) isn’t long enough to generate a new random seed for the default System.Random() constructor.

    public class RandomStringObject

    {

      public RandomStringObject()

      {

        this.s = RandomString(20);

      }

 

      private string s;

 

      public string S

      {

        get { return s; }

      }

    }

 

 

    [Test]

    public void TestRandomString()

    {

      ArrayList randomStringsObjects = new ArrayList();

      for(int i = 0; i < 2000; i ++)

      {

        RandomStringObject rso = new RandomStringObject();

        Assert.IsFalse(randomStringsObjects.Contains(rso.S));

        randomStringsObjects.Add(rso.S);

      }

    }

In order to get this test to pass, you have to increase the Thread.Sleep time, but isn’t really a good solution, since it’s bound to introduce slowness into your code.  A better solution, is to create the Random object once, and simply use it each time you generate a new random number, see these posts here and here for an overview of this.   Unfortunately, this isn’t possible from a static contex (within a constructor for example) since it won’t have access to the object, unless of course you pass in a reference to the Random object, which isn’t really a good solution either. 

A perfect solution?  Well, I’m not sure if there is one, but I did some experimentation, and found that the Hash Code of a Guid (generated by using Guid.NewGuid().GetHashCode()) creates a fairly unique integer, and we can use this as our random seed.

    static internal string RandomString(int size)

    {

 

      Random rand = new System.Random(Guid.NewGuid().GetHashCode());

 

      StringBuilder builder = new StringBuilder();

      char ch ;

      for(int i=0; i<size; i++)

      {

        ch = Convert.ToChar(Convert.ToInt32(26 * rand.NextDouble() + 65)) ;

        if(ch < 0x5B || ch > 0x60) builder.Append(ch);

      }

 

      return builder.ToString();

    }

This code above does a much better job generating the random strings.  Is this useful in any way? I’m not quite sure. Like I said, you'll want to use RNGCryptoServiceProvider for security purposes, like password generation.  I guess the big take away from all this is that you may think you’re code is being random, when it’s actually being very un-random, so watch out!  That is so random!

Brendan


Posted Wed, Mar 9 2005 2:03 PM by Brendan Tompkins

[Advertisement]

Comments

Matt Ranlett wrote re: This is like, so random! Some Randomness from System.Random
on Wed, Mar 9 2005 9:05 PM
The Atlanta C# User Group (www.atlantacsharp.org) just had a meeting where one member used the System.Random namespace to generate some random numbers. We were easily able to see how those numbers, based on the system clock, weren't really random. I'm going to forward this article to him so he has it for future reference. Thanks for the great post.

http://www.devcow.com/weblogs/PermaLink,guid,ac33ae18-d4c6-402e-a646-a729c160afcc.aspx
Sam wrote re: This is like, so random! Some Randomness from System.Random
on Thu, Mar 10 2005 6:32 AM
That's a pretty inventive solution! I like it a lot better than the ThreadSleep. Timing games are such a pain.
Richard Dudley wrote re: This is like, so random! Some Randomness from System.Random
on Thu, Mar 10 2005 12:15 PM
RFC 1750 - Randomness Recommendations for Security (http://www.faqs.org/rfcs/rfc1750.html) covers some of this also, including the problem with clock ticks as seeds. They also have a section on DoD's recommendations for password generation, which talks about various seed values.

One way I've generated different seeds in the same module is to take the clock ticks, and use the left 3 characters as one seed, left 5 as another seed, right 4 as another seed, right 6 as another, ...
TrackBack wrote Java, C#, and VB programmers
on Thu, Mar 10 2005 1:02 PM
TrackBack wrote Java, C#, and VB programmers
on Thu, Mar 10 2005 1:04 PM
me wrote re: This is like, so random! Some Randomness from System.Random
on Wed, Jun 29 2005 12:14 AM
Excellent simple solution. I can now do 3000 or so more simulations in the same amount of time!
Steve Taylor wrote re: This is like, so random! Some Randomness from System.Random
on Tue, Jul 5 2005 5:43 PM
This profoundly improved my speed on a simulation. Thank you.
Jon Galloway wrote Code Puzzle #2 - Generate random fake surnames - Recap
on Sat, Jan 13 2007 12:54 AM

Code Puzzle #2 posed the following task: Write a simple function which generates fake but passable surnames

Dag Johansen wrote re: This is like, so random! Some Randomness from System.Random
on Thu, Oct 23 2008 3:40 PM

Creating a GUID and then computing the hash code from that might work well but it's a rather expensive solution in cpu terms. On a system with a high-resolution timer (these run at the cpu's clock frequency and are ever-increasing so you cannot read the same value twice), in other words on any semi-modern pc, why not use this (modulo int.MaxValue)?

Also, it isn't strictly speaking true that you cannot use the same Random instance from static contexts - you most certainly can. It can be done very simply with a static field and a lock statement (necessary for thread safety). I'm not sure how this would compare performance-wise, especially in a heavily multithreaded app, to the create guid + compute hash code approach, but I suspect favorably.

Vrriclbk wrote re: This is like, so random! Some Randomness from System.Random
on Tue, Jul 14 2009 2:56 PM

2FaJkS

Add a Comment

(required)  
(optional)
(required)  
Remember Me?