Как сгенерировать уникальный номер из 8 цифр? - PullRequest
15 голосов
/ 24 мая 2011

Я использую этот код для генерации 8-значного уникального номера.

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

Этот код действительно генерирует уникальный номер или он может повторить тот же номер снова?

Ответы [ 9 ]

9 голосов
/ 24 мая 2011

GUID - это не просто случайное число;он состоит из сегментов.Некоторые сегменты не изменятся совсем, если guid будет создан на одном компьютере.Используя только 64-битные исходные 128-битные, вы нарушаете структуру guid и, скорее всего, нарушаете уникальность сгенерированного числа.

Этот вопрос содержит больше информации о уникальностииз руководств, проверьте эту ссылку , а также для получения дополнительной информации о том, почему плохо использовать только часть руководства, если вам нужен уникальный номер.

Если вам нужно ограничить дублирование до абсолютногоминимум, добавочный счетчик даст вам то, что вам нужно.Если ваше приложение использует несколько потоков или процессов, счетчик может быть трудно (или даже невозможно) правильно реализовать.

Это область, для которой были разработаны руководства, чтобы быть уникальной на нескольких машинах.Поэтому, если уникальность между машинами является обязательным требованием, вы должны использовать направляющие.Весь гид.

9 голосов
/ 24 мая 2011

Любая случайная последовательность обязательно должна иметь некоторые коллизии. Это только вопрос того, когда. Используя формулу парадокса дня рождения с 100 000 000 возможных значений (8 цифр), вероятность того, что вы столкнетесь только с 10 000 элементов, составляет около 40% и 99% с 30 000 элементов. ( см. Здесь калькулятор ).

Если вам действительно нужна случайная последовательность, вам не следует использовать 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 и поместить его куда-нибудь, чтобы не создавать новый каждый раз.

4 голосов
/ 13 марта 2014

Вот другая версия

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

    }

это гарантирует быть уникальным!

3 голосов
/ 24 мая 2011

Мой первый ответ не касался проблемы уникальности. Мой второй делает:

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

Если вы хотите иметь уникальные номера при перезапуске приложения, вам нужно сохранить значение счетчика в базе данных или где-то еще после каждого вызова GetUniqueNumber.

2 голосов
/ 27 февраля 2017

Этот метод генерирует случайную строку, он не зависит от метода 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% уникальную последовательность, вы должны сохранить старые сгенерированные значения и проверить уникальность вновь созданного значения.

2 голосов
/ 24 мая 2011

Диапазон значений слишком мал. Инкрементный счетчик - это лучшее решение, как в системе ERP: для первого номера клиента установлено значение 1000, а для следующего - 1001, 1002, ..., 99999999. В противном случае, если вы получите случайное число (или часть GUID) из них, вы снова наберете тот же номер. В зависимости от вашего приложения, рано или поздно, но это гарантированно произойдет раньше, чем просто итерирование по ним.

1 голос
/ 24 мая 2011

Если вам нужен уникальный номер от 10000000 до 99999999, начните целое число с 10000000 и просто начните увеличивать его. Генерация последовательно упорядоченных чисел не менее случайна, чем любая другая сгенерированная последовательность, и ее намного проще генерировать.

0 голосов
/ 11 июня 2018
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;
0 голосов
/ 26 января 2017

Если вы выразите «нет» как комбинацию дня (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;
...