1

I want to generate a 9 digit unique random string. Currently I am using

Guid.NewGuid().ToString().Replace("-","").Substring(0,9)

But I am afraid it would have a collision very soon. Is there any better way for this or would this be OK?

Jack
  • 7,433
  • 22
  • 63
  • 107

3 Answers3

4

If you take a sub string of a GUID you are not guaranteed randomness uniqueness at all.

See my answer to a older SO question to fulfill your randomness requirement. Here is the basic code to do it.

public static string CreateRandomString(int length)
{
    length -= 12; //12 digits are the counter
    if (length <= 0)
        throw new ArgumentOutOfRangeException("length");
    long count = System.Threading.Interlocked.Increment(ref counter);
    Byte[] randomBytes = new Byte[length * 3 / 4];
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    rng.GetBytes(randomBytes);

    byte[] buf = new byte[8];
    buf[0] = (byte)count;
    buf[1] = (byte)(count >> 8);
    buf[2] = (byte)(count >> 16);
    buf[3] = (byte)(count >> 24);
    buf[4] = (byte)(count >> 32);
    buf[5] = (byte)(count >> 40);
    buf[6] = (byte)(count >> 48);
    buf[7] = (byte)(count >> 56);
    return Convert.ToBase64String(buf) + Convert.ToBase64String(randomBytes);
}

it gives you 12 digits of counting to prevent collisions and any additional digits you want of randomness. you can modify the code as you want to make shorter than 12 digit strings.

Community
  • 1
  • 1
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • As the OP meanwhile confirmed in the comments on the question that a running (hexadecimal) number is sufficient, I think *random* in the question is simply meant to express *arbitrary*, not true randomness in the mathematical sense. – O. R. Mapper Aug 16 '12 at 07:02
  • @OR Mapper: Yeah hexadecimal will do and even truly random will do. In short I didn't want a running number starting from 000000001. – Jack Aug 16 '12 at 07:04
  • @Jack: But you said so above: *@O. R. Mapper: Yeah that would do.* Note that `000000001` *is* (also) a hexadecimal number. – O. R. Mapper Aug 16 '12 at 07:04
  • @OR Mapper: I still say that would do and even truly random will do. I don't want my number to be as 000000001. I want that to be abcdefcde. – Jack Aug 16 '12 at 07:07
  • @Jack: `abcdefghij` is not a hexadecimal number, but `000000001` is. You are saying that a running hexadecimal number starting at `000000001` will do, but then you also say it won't. Please make up your mind about what you are looking for. – O. R. Mapper Aug 16 '12 at 07:08
  • @O.R Mapper: By mistake I said abcdefghij. I edited the comment before your posted the comment. Please have a look before posting. – Jack Aug 16 '12 at 07:09
  • @Jack: Sorry, the edit arrived here only after I had posted. So, what you're saying is that a running number would be sufficient, but you don't want it to contain any numerical digits (i.e. `0` - `9`)? – O. R. Mapper Aug 16 '12 at 07:10
  • @Scott: Can you please check my answer and let me know if any issues with that? – Jack Aug 16 '12 at 08:08
1

Well, with GUID, it is guaranteed to be globally unique, but only as a whole. You can't assume randomness about a substring of the entire GUID.

Moreover, if you are generating from the same source, there WILL be collisions in substrings because the algorithm uses some of the same variables, for instance the computer's MAC address although I'm not entirely sure about that one. It suffices as an example though.

So if you want to create random strings from substrings of GUIDs, you have to keep track of all the previous GUIDs to make sure there are no collisions. You would get a Las Vegas algorithm.

Davio
  • 4,609
  • 2
  • 31
  • 58
  • 1
    Here is the [IETF v1 implementation of the UUID spec](http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt). Section 3.1.2 shows exactly what bits represent what. – Scott Chamberlain Aug 16 '12 at 07:05
0

I've decided to answer my own question since this is the simplest answer that I found. Credits to Random String Generator Returning Same String

    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();
    }
Community
  • 1
  • 1
Jack
  • 7,433
  • 22
  • 63
  • 107
  • Why are you using `Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65))` instead of [`random.Next(65,91)`](http://msdn.microsoft.com/en-us/library/2dx6wyd4)? However this in no way guarantees uniqueness, per your original requirements. you are just relying on luck to not get the same number twice. – Scott Chamberlain Aug 16 '12 at 12:50
  • @Scott: Thanks for suggesting. The problem is I tried your method but it either gives 8 digits or more due to Base64. I tried all combinations. I want exact 9 characters. Can you please suggest how do I change your method? – Jack Aug 16 '12 at 15:35