Jack
Jack

Reputation: 7557

Random string of length 9 hits collision

I want to generate a random string of length 9.

This is the code which hits collision about 10-15 times. Credits to Random String Generator Returning Same String. Can anybody help me to generate a truly random string?

  class Program
    {

        private static Random random = new Random((int)DateTime.Now.Ticks);
        private static object locker = new object();

        private static string RandomString(int size)
        {
            StringBuilder builder = new StringBuilder();
            char ch;
            for (int i = 0; i < size; i++)
            {
                lock (locker)
                {
                    ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
                }
                builder.Append(ch);
            }

            return builder.ToString();
        }



        static void Main(string[] args)
        {            
            Dictionary<string, string> dict = new Dictionary<string, string>();
            object locker2 = new object();

            ThreadPool.QueueUserWorkItem(new WaitCallback((obj) => {
                for (int i = 0; i < 5000000; i++)
                {
                    string random = RandomString(9);
                    lock (locker2)
                    {
                        if (!dict.ContainsKey(random))
                            dict[random] = random;
                        else
                            Console.WriteLine("Found");
                    }

                }
            }));

            ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
            {
                for (int i = 0; i < 5000000; i++)
                {
                    string random = RandomString(9);
                    lock (locker2)
                    {
                        if (!dict.ContainsKey(random))
                            dict[random] = random;
                        else
                            Console.WriteLine("Found");
                    }

                }
            }));

            ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
            {
                for (int i = 0; i < 5000000; i++)
                {
                    string random = RandomString(9);
                    lock (locker2)
                    {
                        if (!dict.ContainsKey(random))
                            dict[random] = random;
                        else
                            Console.WriteLine("Found");
                    }

                }
            }));

            ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
            {
                for (int i = 0; i < 5000000; i++)
                {
                    string random = RandomString(9);
                    lock (locker2)
                    {
                        if (!dict.ContainsKey(random))
                            dict[random] = random;
                        else
                            Console.WriteLine("Found");
                    }

                }
            }));

            Console.ReadKey();
        }
    }

Upvotes: 0

Views: 769

Answers (3)

CodesInChaos
CodesInChaos

Reputation: 108830

Even using a perfectly random string without constraints, you'll likely get collisions once you generate around 2 million entries. There are 26^9 total strings. Collisions become likely once you hit around the square root of that, which is around 2.3 million. Check out the Birthday problem.

You have a couple of choices:

  • Increase the number of possible strings significantly. This means a longer string, and possibly more characters
  • Keep track of existing values, and reject them.
  • Use a counter and pass it to a pseudo random permutation of the desired size.

Upvotes: 1

primfaktor
primfaktor

Reputation: 2997

Use a GUID and condense that to a string of your liking.

Upvotes: 0

Davin Tryon
Davin Tryon

Reputation: 67316

It might perform as well, but if you need a truly random number you should use the RandomNumberGenerator class. This gives you a crypto-random number and will do a better job distributing the random-ness. This, of course, only really matters if you need crypto-random strings. This SO question does a good job at discussing the difference.

Upvotes: 0

Related Questions