locked
generate unique codes RRS feed

  • Question

  • User-1904303448 posted

    Hi all,

    a question:

    I'm with the following code pretty sure that I generate unique codes?

    for (int i = 0; i < how; i++)
    {
        Random random = new Random();
        int num = random.Next(1000, 9999);
        string tmp = (DateTime.Now.ToString() + i.ToString("x") + num.ToString()).GetHashCode().ToString("x");
    }

    Thanks a lot!

    Tuesday, June 12, 2012 8:37 AM

Answers

All replies

  • User617492218 posted

    use Guid

    technically you could just do this, if you didn't want the date in there

    Guid guid = Guid.NewGuid();
    Console.WriteLine(guid);

    http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx

    but if you wanted the date in there anyways for you to maybe pull it for some reason

    Guid guid = Guid.NewGuid();
    string tmp = string.Format("{0}x{1}", DateTime.Now, guid);
    Console.WriteLine(tmp);
    Tuesday, June 12, 2012 8:49 AM
  • User-1904303448 posted

    There's a problem with guid:

    if I use guid I produce codes too long and complex to be written by an human.

    With my code I produce codes like that:

    8a3ebc8f

    and it's perfect considering the fact that a user with a tablet must write it in a textbox.

    My thought is that using date in combination of hash code and random numbers could be enough, but I'm not sure, also considering the shortness of the string.

    Do u think that this way I have uniques codes?

    Tuesday, June 12, 2012 9:07 AM
    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, June 12, 2012 9:28 AM
  • User-1904303448 posted

    Thanks, the first link fits perfectly my needs

    Tuesday, June 12, 2012 11:04 AM
  • User-434868552 posted

    @ dofoo

    Random random = new Random();     // seed

    minor point:  http://msdn.microsoft.com/en-us/library/system.random.aspx
    http://msdn.microsoft.com/en-us/library/h343ddh9.aspx "Random Constructor"

    your seed should be outside of your for loop:

    Random random = new Random();         // seed 
    for (int i = 0; i < how; i++) 
    { 
        int num = random.Next(1000, 9999); 
        string tmp = (DateTime.Now.ToString() + i.ToString("x") + num.ToString()).GetHashCode().ToString("x"); 
    }

    g.

    Tuesday, June 12, 2012 11:16 AM
  • User-434868552 posted

    @ dofoo

    your code is interesting; eventually, over a long period of time, it would return at least one duplicate because the Object.GetHashCode method returns a System.Int32;  i.e., your unique codes will be based upon a finite range of numbers, Int32.MinValue through Inte32.MaxValue, inclusive.

    http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

    the question that comes to mind is what you intend to do with your pseudo-unique code?; example, if you're using it for a database key, you must first test whether the record exists before adding a row to your database table ... if the record exists, your would keep generating your pseudo-unique codes until finally a record did not exist having your just generated pseudo-unique code.

    g.

    your code, expanded to show intermediate parts:

    Int32 how = 32;
    Random random = new Random();
    Console.WriteLine ("i, hex_i, num, numToString, length, tmp, tmpAsHexHashCode, tmpAsHashCode, tmpToHash, dateTimeNow");
    for (int i = 0; i < how; i++) 
    { 
        int num                 = random.Next(1000, 9999);
        String dateTimeNow      = DateTime.Now.ToString();
        String hex_i            = i.ToString("x");
        String numToString      = num.ToString();
        string tmpToHash        = dateTimeNow + hex_i + numToString;
        Int32  tmpAsHashCode    = tmpToHash.GetHashCode(); 
        String tmpAsHexHashCode = tmpAsHashCode.ToString("x"); 
        string tmp              = (dateTimeNow + i.ToString("x") + num.ToString()).GetHashCode().ToString("x"); 
        Console.WriteLine("{0} | {1} | {2} | {3} | {4} | {5} | {6} | {7} | {8} | {9}",
        i, hex_i, num, numToString, tmp.Length, tmp, tmpAsHexHashCode, tmpAsHashCode, tmpToHash, dateTimeNow);
    }

    example output:

    i, hex_i, num, numToString, length, tmp, tmpAsHexHashCode, tmpAsHashCode, tmpToHash, dateTimeNow
    0 | 0 | 6636 | 6636 | 8 | f765d79a | f765d79a | -144320614 | 2012-06-12 12:04:1406636 | 2012-06-12 12:04:14
    1 | 1 | 5425 | 5425 | 8 | d8266302 | d8266302 | -668572926 | 2012-06-12 12:04:1415425 | 2012-06-12 12:04:14
    2 | 2 | 7116 | 7116 | 8 | ff23c0d1 | ff23c0d1 | -14434095 | 2012-06-12 12:04:1427116 | 2012-06-12 12:04:14
    3 | 3 | 9694 | 9694 | 8 | b4601bef | b4601bef | -1268769809 | 2012-06-12 12:04:1439694 | 2012-06-12 12:04:14
    4 | 4 | 7225 | 7225 | 8 | 650b6300 | 650b6300 | 1695245056 | 2012-06-12 12:04:1447225 | 2012-06-12 12:04:14
    5 | 5 | 6659 | 6659 | 8 | a214933c | a214933c | -1575709892 | 2012-06-12 12:04:1456659 | 2012-06-12 12:04:14
    6 | 6 | 5912 | 5912 | 8 | 52b3c0d3 | 52b3c0d3 | 1387512019 | 2012-06-12 12:04:1465912 | 2012-06-12 12:04:14
    7 | 7 | 6329 | 6329 | 8 | 693562ff | 693562ff | 1765106431 | 2012-06-12 12:04:1476329 | 2012-06-12 12:04:14
    8 | 8 | 9271 | 9271 | 8 | 1fa8a9fd | 1fa8a9fd | 531147261 | 2012-06-12 12:04:1489271 | 2012-06-12 12:04:14
    9 | 9 | 3784 | 3784 | 8 | bcada75a | bcada75a | -1129470118 | 2012-06-12 12:04:1493784 | 2012-06-12 12:04:14
    10 | a | 9833 | 9833 | 8 | 2183d791 | 2183d791 | 562288529 | 2012-06-12 12:04:14a9833 | 2012-06-12 12:04:14
    11 | b | 8921 | 8921 | 8 | 8daa62f5 | 8daa62f5 | -1918213387 | 2012-06-12 12:04:14b8921 | 2012-06-12 12:04:14
    12 | c | 1983 | 1983 | 8 | cc8ca75c | cc8ca75c | -863197348 | 2012-06-12 12:04:14c1983 | 2012-06-12 12:04:14
    13 | d | 2935 | 2935 | 8 | f2c7d796 | f2c7d796 | -221784170 | 2012-06-12 12:04:14d2935 | 2012-06-12 12:04:14
    14 | e | 3737 | 3737 | 8 | d400d797 | d400d797 | -738142313 | 2012-06-12 12:04:14e3737 | 2012-06-12 12:04:14
    15 | f | 8943 | 8943 | 8 | e7d51e97 | e7d51e97 | -405463401 | 2012-06-12 12:04:14f8943 | 2012-06-12 12:04:14
    16 | 10 | 6924 | 6924 | 8 | b609e129 | b609e129 | -1240866519 | 2012-06-12 12:04:14106924 | 2012-06-12 12:04:14
    17 | 11 | 9335 | 9335 | 8 | 117c9d2d | 117c9d2d | 293379373 | 2012-06-12 12:04:14119335 | 2012-06-12 12:04:14
    18 | 12 | 4493 | 4493 | 8 | fa00e389 | fa00e389 | -100605047 | 2012-06-12 12:04:14124493 | 2012-06-12 12:04:14
    19 | 13 | 2289 | 2289 | 8 | 9e6d2844 | 9e6d2844 | -1637013436 | 2012-06-12 12:04:14132289 | 2012-06-12 12:04:14
    20 | 14 | 9843 | 9843 | 8 | 57e16d0f | 57e16d0f | 1474391311 | 2012-06-12 12:04:14149843 | 2012-06-12 12:04:14
    21 | 15 | 5929 | 5929 | 8 | b5a6e203 | b5a6e203 | -1247354365 | 2012-06-12 12:04:14155929 | 2012-06-12 12:04:14
    22 | 16 | 1886 | 1886 | 8 | ce1d6cce | ce1d6cce | -836932402 | 2012-06-12 12:04:14161886 | 2012-06-12 12:04:14
    23 | 17 | 7060 | 7060 | 8 | 56111205 | 56111205 | 1443959301 | 2012-06-12 12:04:14177060 | 2012-06-12 12:04:14
    24 | 18 | 8832 | 8832 | 8 | 9f096b84 | 9f096b84 | -1626772604 | 2012-06-12 12:04:14188832 | 2012-06-12 12:04:14
    25 | 19 | 1403 | 1403 | 8 | c91ee326 | c91ee326 | -920722650 | 2012-06-12 12:04:14191403 | 2012-06-12 12:04:14
    26 | 1a | 2945 | 2945 | 8 | f9e3ebbb | f9e3ebbb | -102503493 | 2012-06-12 12:04:141a2945 | 2012-06-12 12:04:14
    27 | 1b | 4270 | 4270 | 8 | 9c06321a | 9c06321a | -1677315558 | 2012-06-12 12:04:141b4270 | 2012-06-12 12:04:14
    28 | 1c | 9869 | 9869 | 8 | 411776d2 | 411776d2 | 1092056786 | 2012-06-12 12:04:141c9869 | 2012-06-12 12:04:14
    29 | 1d | 4673 | 4673 | 8 | 26a4054d | 26a4054d | 648283469 | 2012-06-12 12:04:141d4673 | 2012-06-12 12:04:14
    30 | 1e | 7623 | 7623 | 8 | 6dcc05ac | 6dcc05ac | 1842087340 | 2012-06-12 12:04:141e7623 | 2012-06-12 12:04:14
    31 | 1f | 8804 | 8804 | 8 | 2a6e7700 | 2a6e7700 | 711882496 | 2012-06-12 12:04:141f8804 | 2012-06-12 12:04:14



    Tuesday, June 12, 2012 12:04 PM
  • User-434868552 posted

    @ RameshRajendran

    http://www.randomcodegenerator.nl/ is interesting ... the downside appears to be this restriction:

    This tool can generate up to 250 unique random codes at a time.

    If you own a Random Code Generator account, it can generate 100.000!

    g.

     edit:  they are currently selling an account for 25 euros

    Tuesday, June 12, 2012 12:35 PM
  • User-434868552 posted

    @ dofoo

    pretty sure that I generate uinique codes

    FWIW, if you requre "unique codes", "pretty sure" is insufficient.

    i've run variations* on code downloaded from the article http://www.codeproject.com/Articles/14403/Generating-Unique-Keys-in-Net suggested by RameshRajendran above.

    N.B.:       ¡    almost certainly, duplicates ARE produced  !

    N.B.:       ¡    my investigation is not complete  !

    in one test, my first duplicate was encountered after 2 379 101 (two million iterations).

    in many tests, i run out of memory ('System.OutOfMemoryException') before encountering a duplicate.

    dofoo, i've not tested your method for duplicates; your method should produce more duplicates because it's the hexadecimal value of an Int32 ... the method from

    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";

    to me, it appears the above string is the major influence on 's algorithm ... you have (26 + 26 + 10) characters for each of eight character positions, i.e., 62 to the eight power ... a very large number but nevertheless a finite number.

    WHENEVER one is dealing with finite combinations, if unique values are required, it is prudent to check for duplicates!

    g.

    * code variation (this variation has imperfections, especially in the catch block):

    void Main()
    {
        Dictionary<String, Int32> rngCharacterMask = new Dictionary<String, Int32>();
        Int32 exceptionCount = 0;
        List<String> duplicates = new List<String>();
        Int32 firstDuplicate = -666;
        Boolean isFirstDuplicate = true;
        String firstExceptionMessage = "no exceptions";
        Int32 secondDuplicate = -666;
        Boolean isSecondDuplicate = true;
        String secondExceptionMessage = "no second exception";
        Int32 lastDuplicate = -666;
        String lastExceptionMessage = "???";
        Console.WriteLine(DateTime.Now);
        Int32 maxiumIterations = 100000000;
        Console.WriteLine ("maxiumIterations:  {0}", maxiumIterations);
        for (Int32 i = 0; i < maxiumIterations; i++)
        {
            String getRNGCharacterMask = RNGCharacterMask();
            try
            {	        
               rngCharacterMask.Add(getRNGCharacterMask, i);
            }
            catch (Exception ex)
            {
                if(ex.Message == "Exception of type 'System.OutOfMemoryException' was thrown.:  " )
                {
                    Console.WriteLine(DateTime.Now);
                    Console.WriteLine(i);
                    if(!isSecondDuplicate)
                        throw new NotImplementedException("todo:  handle Exception of type 'System.OutOfMemoryException' was thrown.");
                }
                if(i>19999999) throw new NotImplementedException("todo:  any exceptions yet?");
                if (isFirstDuplicate)
                {
                    Console.WriteLine("first duplicate at {0}", DateTime.Now);
                    Console.WriteLine(DateTime.Now);
                    Console.WriteLine (getRNGCharacterMask);
                    firstDuplicate = i;
                    firstExceptionMessage = ex.Message;
                    isFirstDuplicate = false;
                    Console.WriteLine("{0}:  isFirstDuplicate", isFirstDuplicate);
                    Console.WriteLine("{0}:  firstDuplicate", firstDuplicate);
                    Console.WriteLine("{0}:  message", firstExceptionMessage);
                }
                else if (isSecondDuplicate)
                {
                    Console.WriteLine("second duplicate at {0}", DateTime.Now);
                    Console.WriteLine (getRNGCharacterMask);
                    secondDuplicate        = i;
                    secondExceptionMessage = ex.Message;
                    Console.WriteLine("{0}:  isFirstDuplicate", isFirstDuplicate);
                    isSecondDuplicate      = false;
                    Console.WriteLine("{0}:  isSecondDuplicate", isSecondDuplicate);
                    Console.WriteLine("{0}:  secondDuplicate", secondDuplicate);
                    Console.WriteLine("{0}:  message", secondExceptionMessage);
                }
                exceptionCount++;
                duplicates.Add(getRNGCharacterMask);
                lastDuplicate = i;
                lastExceptionMessage = ex.Message;
            }
        }
        Console.WriteLine("Finished {0} iterations at {1}", maxiumIterations, DateTime.Now);
        Console.WriteLine (rngCharacterMask.Count.ToString());
        Console.WriteLine("{0}:  duplicates", duplicates.Count);
        Console.WriteLine("{0}:  isFirstDuplicate", isFirstDuplicate);
        Console.WriteLine("{0}:  firstDuplicate", firstDuplicate);
        Console.WriteLine("{0}:  message", firstExceptionMessage);
        Console.WriteLine("{0}:  isSecondDuplicate", isSecondDuplicate);
        Console.WriteLine("{0}:  secondDuplicate", secondDuplicate);
        Console.WriteLine("{0}:  message", secondExceptionMessage);
        Console.WriteLine("{0}:  lastDuplicate", lastDuplicate);
        Console.WriteLine("{0}:  message", lastExceptionMessage);
    }
    
    public string RNGCharacterMask()
    {
    	int maxSize  = 8 ;
    	char[] chars = new char[62];
    	string a;
    	a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
    	chars = a.ToCharArray();
    	int size  = maxSize ;
    	byte[] data = new byte[1];
        // http://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider.aspx
    	System.Security.Cryptography.RNGCryptoServiceProvider
          crypto = new System.Security.Cryptography.RNGCryptoServiceProvider();
    	crypto.GetNonZeroBytes(data) ;
    	size =  maxSize ;
        
        data = new byte[size];
    	crypto.GetNonZeroBytes(data);
    	StringBuilder result = new StringBuilder(size) ;
    	foreach(byte b in data )
    		{
    //          Console.Write("{0}: ", b);
                result.Append(chars[b % (chars.Length - 1)]);
            }
    	return result.ToString();
    }


     

    Tuesday, June 12, 2012 4:30 PM
  • User-1904303448 posted

    Very interesting, thank you @gerrylowry

    I think that rngCharacterMask is sufficient for me because I check for every interation if the code exist. This is a little bit heavy for the server but the problem is that I don't generate ALL the codes in one time, but in different times.

    I have a page where I declare how many codes I need and then I generate them. So basically my initial code could be sufficient but I been not sure if using date could be sufficient for not use a query to check if the same code was previously generated.

    Now I have clearly in mind what "unique" means in .net, thank you again

    Wednesday, June 13, 2012 4:22 AM
  • User-434868552 posted

    @ dofoo

    Very interesting, thank you @gerrylowry

    my pleasure ...

    I think that rngCharacterMask is sufficient for me because I check for every interation if the code exist.

    yes .... you are correct.

    i ran my test about a dozen times ... once a duplicate was discovered at 6 728 020 (almost seven million) ... most of the time, i ran out of memory before finding duplicates.

    N.B.:  i modified my test to use your tecnnique ... i hit the first duplicate at 71463 and the second at 79080, both less than 100 000.

    a second test using your method found duplicates at 26277, 80832, 86264, 103866, 105676, 116469, 121490, 128238, 131578, 190715, 193123, 196291, 207278, 214973, 228881, 228997, 237301, 239698, 245300, 286593, ...

    Now I have clearly in mind what "unique" means in .net,

    such is the problem with computers ... i.e., computers do exactly what we tell them to do ... so we really need to be careful with the instructions that we provide ... humans tend to be forgiving while computers tend to be unforgiving.

    thank you again

    again, my pleasure

    g.

    Wednesday, June 13, 2012 11:53 AM
  • User1808797856 posted

    hello,

    you can create the unique key, by the following code

    DateTime.Now.Ticks.ToString("X")

    which generates:

     8c8113da982d75a

    and which is getting a bit long at 15 characters. Ticks is a 64 bit so it makes sense that the string is a bit longer.

    thanks

    Saturday, June 22, 2013 6:59 AM