Tuesday, June 5, 2007

Random Number Generation! Some Tips

I worked on a serial key generator for my office a while back and I just wanted to share how I went about experimenting on how to get the generator to work "just right". The first of the many problems that I encountered, was that my generator churned out keys faster than a 8085 computer rendering a frame in Half-Life 2. For the uninitiated, that is dead slow. The code of the turtle generator goes something like this (C# code):

public class MyRandomGenerator
{
public MyRandomGenerator()
{

//Intentionally empty!

}

/*This method returns a random integer that is rounded off.*/
public int RandomNumber()
{
/*
Instantiates a new Random object, and is automatically seeded by your
your computer's system time*/
Random randomObject = new Random();
int anInteger = 0;

/*
Makes the computer sleep for 1 millisecond and gets an absolute
random integer.*/

Thread.Sleep(1);
anInteger = Math.Abs(randomObject.Next());

return anInteger;
}// end of RandomNumber
}// end of MyRandomGenerator

public partial class WindowsForm : Form
{
/*Instantiates a new MyRandomGenerator oject and
invokes the RandomNumber method*/
for (int i; i<
neededNumber; i++)
{
MyRandomGenerator randomNumber = new MyRandomGenerator();
neededNumber = randomNumber.RandomNumber();
}//end of for loop
}//end of WindowsForm

The code above does the generation without a hitch, but if you try to include it in a loop that iterates about a million times, the random generation would take hours or even hang. This is because of the Thread.Sleep(1) method. The method's execution time seems to increase exponentially everytime the new sleep is invoked. But removing the Thread.Sleep drastically reduces the generation's randomness and would produce weak codes. And you'll notice that everytime the Form needs a new number it instantiates a new copy of the MyRandomGenerator which poses the same problem of randomness. This poses a problem of number or key duplicates, which is a very big no-no. To solve the two problems I came up with the following solution:

public class RandomNumberGenerator
{
/*The protected access modifier allows only classes within the super class to access the variable, while the static modifier implies that the variable would be unique within the scope of the class. This partly solves the two problems, enforcing only one object to be instantiated by a calling class.*/
protected static Random m_randomNumber;

/*This constructor further enforces the single object rule we have to
impose to our random generation. The variable is now seeded once.*/
static RandomNumberGenerator()
{
m_randomNumber = new Random();
}
/*Now the random number is generated using our static variable.*/
public int Next()
{
return Math.Abs(m_randomNumber.Next());
}//end of Next
}//end of
RandomNumberGenerator

public partial class WindowsForm : Form
{
/*We first instantiate the object we need outside the iteration loop.*/
RandomNumberGenerator randomObject = new RandomNumberGenerator();

for (int i; i int aNumber = 0; i++)
{
aNumber = randomObject.Next();
}//end of for loop
}//end of WindowsForm


The new version of the random number generator should now be randomly safe and it very unlikely that duplicates would pop up. I tested this code and found no duplicates for every 10000 keys generated. I have yet to test this against a million keys.

I do hope that this helps , Happy Coding!




Permalink

No comments: