Как я могу создать уникальный 7-значный код для объекта? - PullRequest
10 голосов
/ 11 февраля 2010

Когда пользователь добавляет новый элемент в мою систему, я хочу создать уникальный не приращающийся псевдослучайный 7-значный код для этого элемента.Количество созданных элементов будет исчисляться только тысячами (<10 000). </p>

Поскольку он должен быть уникальным и никакие два элемента не будут иметь одинаковую информацию, я мог бы использовать хеш, но это должен бытькод, которым они могут поделиться с другими людьми - отсюда и 7 цифр.

Моя первоначальная мысль заключалась в том, чтобы просто зациклить генерацию случайного числа, убедиться, что оно еще не использовалось, и, если оно было, промыть и повторить,Я думаю, что это разумное, если неприятное решение, учитывая низкую вероятность столкновений.

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

У кого-нибудь есть лучший способ?

Ответы [ 11 ]

15 голосов
/ 11 февраля 2010

Выберите 7-значное простое число число A и большое простое число число B и

int nth_unique_7_digit_code(int n) {
    return (n * B) % A;
}

Количество всех уникальных кодов, сгенерированных этим, будет A .

Если вы хотите быть более «безопасным», выполните pow(some_prime_number, n) % A, т.е.

static int current_code = B;
int get_next_unique_code() {
   current_code = (B * current_code) % A;
   return current_code;
}
5 голосов
/ 11 февраля 2010

Вы можете использовать инкрементный идентификатор, а затем XOR на некотором фиксированном ключе.

const int XORCode = 12345;

private int Encode(int id)
{
    return id^XORCode;
}

private int Decode(int code)
{
    return code^XORCode;
}
4 голосов
/ 11 февраля 2010

Честно говоря, если вы хотите сгенерировать только пару тысяч 7-значных кодов, в то время как будет доступно 10 миллионов различных кодов, я думаю, достаточно просто сгенерировать случайный код и проверить наличие коллизии.

Вероятность столкновения при первом попадании будет, в худшем случае, около 1 на тысячу, а вычислительные усилия по генерации нового 7-значного кода и повторной проверке столкновения будут намного меньше. чем вести словарь или аналогичные решения.

Использование GUID вместо 7-значного кода, как предлагается для гаррионов, также, безусловно, будет работать, но, конечно, GUID будет немного сложнее запомнить для ваших пользователей.

2 голосов
/ 11 февраля 2010

У вас <10.000 предметов, поэтому вам нужно всего 4 цифры, чтобы сохранить уникальный номер для всех предметов.Поскольку у вас есть 7 цифр, у вас есть еще 3 цифры. </p>

Если вы объедините уникальный порядковый номер из 4 цифр со случайным числом из 3 цифр, вы будете уникальными и случайными.Вы увеличиваете порядковый номер с каждым новым сгенерированным идентификатором.

Вы можете просто добавить их в любом порядке или смешать их.

seq = abcd, rnd = ABC

Вы можете создать следующие ID:

  • abcdABC
  • ABCabcd
  • aAbBcCd

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

2 голосов
/ 11 февраля 2010

Я предполагаю, что у вас будет таблица из сгенерированных . В этом случае я не вижу проблемы с выбором случайных чисел и проверкой их по базе данных, но я бы не стал делать это по отдельности. Генерация их обходится дешево, выполнение запросов к БД относительно затратно. Я бы генерировал 100 или 1000 за раз, а затем спрашивал у БД, какая из них существует. Держу пари, что вам не придется делать это дважды в большинстве случаев.

2 голосов
/ 11 февраля 2010

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

Тем не менее, некоторые базы данных предлагают генератор / последовательность "случайный идентификатор", который уже возвращает идентификаторы в диапазоне в случайном порядке.

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

2 голосов
/ 11 февраля 2010

Я бы предложил использовать guid вместо 7-значного кода, поскольку он будет более уникальным, и вам не нужно беспокоиться о его генерации, поскольку .NET сделает это за вас.

1 голос
/ 11 февраля 2010

Я бы попытался использовать LFSR (регистр сдвига с линейной обратной связью), код действительно прост, вы можете найти примеры везде, например Википедия , и хотя он не криптографически защищен, он выглядит очень случайным. Также реализация будет очень быстрой, так как она использует в основном операции сдвига.

0 голосов
/ 11 февраля 2010

Ну, вы могли бы попросить пользователя выбрать свой собственный 7-значный номер и проверить его по совокупности существующих номеров (которые вы бы сохранили, поскольку они были израсходованы), но я подозреваю вас будет фильтровать много ответов типа 1234567, 7654321, 9999999, 7777777 и может потребоваться несколько RegEx для достижения фильтрации, плюс вам нужно будет предупреждать пользователя о таких последовательностях, чтобы не было плохого, повторяющегося ввода пользователя опыт.

0 голосов
/ 11 февраля 2010

Вероятность попадания очень мала.
Например, у вас есть 10 ^ 4 пользователей и 10 ^ 7 возможных идентификаторов.
Вероятность того, что вы выбрали использованный идентификатор 10 раз подряд, теперь равна 10 ^ -30.
Этот шанс ниже, чем один раз в жизни любого человека.

...