如何生成唯一的 8 位数字?

发布于 2024-11-09 11:03:29 字数 194 浏览 0 评论 0原文

我正在使用此代码生成一个 8 位唯一编号。

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

这段代码真的会生成一个唯一的数字吗?还是可能会再次重复相同的数字?

I am using this code 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

乖乖哒 2024-11-16 11:03:29

GUID 不仅仅是一个随机数;它也是一个随机数。它由段组成。如果 guid 是在同一台计算机上生成的,则某些段根本不会改变。通过仅使用原始 128 位中的 64 位,您将破坏 guid 的结构,并且很可能破坏生成的数字的唯一性。

这个问题有关于guid唯一性的更多信息,请检查此链接以及有关为什么不好的更多信息如果您需要唯一的编号,则仅使用 guid 的一部分。

如果您需要将重复次数限制在绝对最小值,增量计数器将满足您的需要。如果您的应用程序使用多个线程或进程,则计数器可能很难(甚至不可能)正确实现。

这就是指南设计的目的,在多台机器上是唯一的。因此,如果需要跨机器的唯一性,您应该使用指南。整个指南。

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.

把时间冻结 2024-11-16 11:03:29

任何随机序列都必然会发生一些冲突。这只是时间问题。使用生日悖论公式,如果有 100,000,000 个可能的值(8 位数字),则仅与 10,000 个元素发生碰撞的可能性约为 40%,而与 30,000 个元素发生碰撞的可能性约为 99%。 (请参阅此处的计算器)。

如果您确实需要随机序列,则不应将 GUID 用于此目的。 GUID 具有非常具体的结构,只能将其视为一个整体。创建随机 8 位序列生成器非常容易。这将为您提供一个 8 位数字序列:

 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);
 }

您还可以将 RandomNumberGenerator 放置在某处,以避免每次都创建一个新的序列。

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.

橘寄 2024-11-16 11:03:29

这是另一个版本,

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");

    }

它保证是独一无二的!

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!

清秋悲枫 2024-11-16 11:03:29

我的第一个答案没有解决唯一性问题。我的第二个是:

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

如果您希望在应用程序重新启动时拥有唯一的数字,则需要在每次 GetUniqueNumber 调用后将计数器的值保留到数据库或其他位置。

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.

惟欲睡 2024-11-16 11:03:29

值的范围太小。递增计数器是最好的解决方案,就像在 ERP 系统中一样 - 您将第一个客户编号设置为 1000,下一个客户编号为 1001、1002、...、99999999。否则,如果您从中获得随机数(或 GUID 的一部分),您将再次输入相同的数字。根据您的应用程序,迟早会发生,但肯定会比仅仅迭代它们更快。

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.

饮惑 2024-11-16 11:03:29

此方法将生成一个随机字符串,它不依赖于 Random 方法,并且比 guid 方法要好得多:

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));
}

您可以增加长度以减少碰撞机会,但要获得 100% 唯一的序列,您必须坚持旧生成的值并检查新创建的值的唯一性。

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.

棒棒糖 2024-11-16 11:03:29

如果您想要 10000000 到 99999999 之间的唯一数字,请从 10000000 开始一个整数,然后开始递增。生成顺序排列的数字并不比任何其他生成的序列更随机,而且更容易生成。

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.

屋顶上的小猫咪 2024-11-16 11:03:29

如果您将编号表示为日(2 位数字)、小时(2 位数字)、分钟(2 位数字)、秒(2 位数字)和年份(4 位数字)的组合,那么它将是 12 位数字,但始终是唯一的编号。

 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;

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;
迟月 2024-11-16 11:03:29
System.Threading.Thread.Sleep(1);
long code = (long)DateTime.UtcNow.Subtract(new DateTime(2018, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;

或者

System.Threading.Thread.Sleep(1000);
long code = (long)DateTime.UtcNow.Subtract(new DateTime(2018, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文