开发者

How to Generate Unique Number of 8 digits?

I am using this co开发者_如何学运维de to generate a 8 digit unique number.

byte[] buffer = Guid.NewGuid().ToByteArray();
return BitConverter.ToUInt32(buffer, 8).ToString();

Does this code really generate a unique number or might it repeat the same number again?


A GUID is not just a random number; it's composed of segments. Some of the segments will not change at all if the guid is generated on the same computer. By using only 64-bits of the original 128-bits you are breaking the structure of the guid and most likely breaking the uniqueness of the generated number.

This question has more info on uniqueness of guids, check this link as well for more info on why it's bad to use only part of a guid if you need a unique number.

If you need to limit duplication to an absolute minimum, an incremental counter will give you what you need. If your application is using multiple threads or processes, a counter may be hard (or even impossible) to implement correctly.

This is the realm that guids were designed for, to be unique across multiple machines. So if uniqueness across machines is a requirement you should use guids. The whole guid.


Any random sequence is bound to have some collisions. It's just a matter of when. Using the birthday paradox formula, with 100,000,000 possible values (8 digits), the chance that you will have a collision with only 10,000 elements is around 40% and 99% with 30,000 elements. (see here for a calculator).

If you really need a random sequence, you should not use a GUID for this purpose. GUIDs have very specific structure and should only be taken as a whole. It is easy enough to create a random 8 digit sequence generator. This should give you an 8 digit sequence:

 public string Get8Digits()
 {
   var bytes = new byte[4];
   var rng = RandomNumberGenerator.Create();
   rng.GetBytes(bytes);
   uint random = BitConverter.ToUInt32(bytes, 0) % 100000000;
   return String.Format("{0:D8}", random);
 }

You can also take the RandomNumberGenerator and place it somewhere to avoid creating a new one everytime.


Here is another version

public static string GetFormNumber()
    {
        byte[] buffer = Guid.NewGuid().ToByteArray();
        var FormNumber = BitConverter.ToUInt32(buffer, 0) ^ BitConverter.ToUInt32(buffer, 4) ^ BitConverter.ToUInt32(buffer, 8) ^ BitConverter.ToUInt32(buffer, 12);
        return FormNumber.ToString("X");

    }

it assures to be unique!


My first answer did not address the uniqueness problem. My second one does:

static int counter;
public static int GetUniqueNumber()
{ 
    return counter++; 
}

If you want to have unique numbers across app restarts, you need to persist the value of counter to a database or somewhere else after each and every GetUniqueNumber call.


The range of values is too small. An incrementing counter is the best solution, like in an ERP system - you set the first customer number to 1000 and the next one is 1001, 1002,...,99999999. Otherwise, if you get a random number (or part of GUID) from these, you'll hit the same number again. Depending on your app, sooner or later but it's guaranteed to happen sooner than just iterating over them.


This method will generate a random string, it doesn't rely on the Random method and also is far better than the guid approch :

public static string gen_Digits(int length)
{
    var rndDigits = new System.Text.StringBuilder().Insert(0, "0123456789", length).ToString().ToCharArray();
    return string.Join("", rndDigits.OrderBy(o => Guid.NewGuid()).Take(length));
}

you can increase the length for less collision chance, but to have a 100% unique sequence you have to persist the old generated values and check the newly created value for uniquness.


If you want a unique number between 10000000 and 99999999, start an integer from 10000000 and just start incrementing it. Generating sequentially ordered numbers is no less random than any other generated sequence, and a whole lot easier to generate.


If you express the no as a combination of day( 2digit), hour(2digit), minute(2digit), second(2digit) and year ( 4 digit) , then it will be 12 digit but always unique no.

 DateTime _now = DateTime.Now;
 string _dd = _now.ToString("dd"); //
 string _mm = _now.ToString("MM");
 string _yy = _now.ToString("yyyy");
 string _hh = _now.Hour.ToString();
 string _min = _now.Minute.ToString();
 string _ss = _now.Second.ToString();

 string _uniqueId= _dd+ _hh+ _mm+_min+_ss + _yy;


System.Threading.Thread.Sleep(1);
long code = (long)DateTime.UtcNow.Subtract(new DateTime(2018, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;

OR

System.Threading.Thread.Sleep(1000);
long code = (long)DateTime.UtcNow.Subtract(new DateTime(2018, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜