The code for this article applies to C#
Reading blogs, I found this post (in italian), where Marco wants to write a function to generate random numbers with the following rules:
- 5 digits long
- result should be returned in a string
- all the digits should be different (on each result you can't have two of the same digit)
The function he came up with was the following:
private string GetRandom()
{
Random rn = new Random();
string resultnum=string.Empty;
do
{
string a = rn.Next(0, 9).ToString();
if (resultnum.Contains(a)!=true)
resultnum = resultnum + a;
}
while (resultnum.Length<5);
return resultnum;
}
I felt curious to see what areas I could improve, and I started writing a function to get the same result, but in a more optimized way
A couple things that jump out to my mind are:
- string concatenation
- the loop and comparing each time to see if the digit is in the result already
So I wanted to write a function that: would avoid concatenation and would execute the loop exactly 5 times, this is the result:
static char[] allNumbers = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
Random r = new Random();
public string GetRandom2() {
char[] result = new char[5];
int max = 9, pos=0;
for (int i=1; i<6; i++) {
pos = r.Next(0, max);
result[i - 1] = allNumbers[pos];
//*** swap positions
allNumbers[pos] ^= allNumbers[max];
allNumbers[max] ^= allNumbers[pos];
allNumbers[pos] ^= allNumbers[max--];
}
return new string(result);
}
The technique I used was:
- Have a predefined array with all possible characters
- I have a variable max that I use to call the method Random.Next(0, max)
- the variable is decremented on each iteration
- I swap the digit from the result to the last position, with this I leave this digit out of the posibilities for the next call
The performance gain from these changes was minimal (3 ms per 1000 calls), then I thought about moving the Random variable declaration outside the function, so it could be reused between calls, this gave me the performance gain I was looking for, calling the function 10,000 times takes ~114ms using the old method and only ~6ms using the new one, that's where the problem was, the rest was pretty much insignificant =o(
I'm sure someone else can write a faster version, but I accomplished my goal =o)
No comments:
Post a Comment