如何生成 8 位的唯一数字

本文关键字:唯一 数字 何生成 | 更新日期: 2023-09-27 17:57:20

我正在使用此代码生成一个 8 位的唯一数字。

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

此代码是否真的生成一个唯一的数字,或者它可能会再次重复相同的数字?

如何生成 8 位的唯一数字

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

此问题包含有关 guid 唯一性的更多信息,请查看此链接,了解有关为什么在需要唯一编号时仅使用部分 guid 是不好的的详细信息。

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

这是 GUID 设计的目的领域,在多台计算机上是唯一的。因此,如果要求跨计算机的唯一性,则应使用 GUID。整个指南。

任何随机序列都必然会发生一些冲突。这只是时间问题。 使用生日悖论公式,使用 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);
 }

您也可以使用随机数生成器并将其放置在某个位置,以避免每次都创建一个新的。

这是另一个版本

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

它保证是独一无二的!

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

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

如果要在应用重新启动期间具有唯一编号,则需要在每次 GetUniqueNumber 调用后将计数器的值保留到数据库或其他位置。

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

此方法将生成一个随机字符串,它不依赖于 Random 方法,也比 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));
}

您可以增加长度以减少冲突几率,但要获得 100% 唯一的序列,您必须保留旧的生成值并检查新创建的值的单性。

如果你想要一个介于 10000000 和 99999999 之间的唯一数字,请从 10000000 开始一个整数,然后开始递增它。生成顺序排序的数字的随机性不亚于任何其他生成的序列,并且更容易生成。

如果您将 no 表示为日(2 位)、小时(2 位)、分钟(2 位)、秒(2 位)

和年( 4 位)的组合,那么它将是 12 位,但始终是唯一的 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;

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