Как уже говорили другие, # 4 - лучший метод, когда не используется библиотечный метод. Тем не менее, вы всегда должны ставить null в левой части сравнения, чтобы случайно не назначить null для foo в случае опечатки. В этом случае компилятор поймает ошибку.
// You meant to do this
if(foo != null){
// But you made a typo like this which will always evaluate to true
if(foo = null)
// Do the comparison in this way
if(null != foo)
// So if you make the mistake in this way the compiler will catch it
if(null = foo){
// obviously the typo is less obvious when doing an equality comparison but it's a good habit either way
if(foo == null){
if(foo = null){
Я также пришел с такой же проблемой, но в C #. Я наконец решил это. Надеюсь, что это работает и для вас.
Предположим, мне нужно случайное число от 0 до некоторого MaxValue
и наличие объекта случайного типа, скажем, случайного.
int n=0;
while(n<MaxValue)
{
int i=0;
i=random.Next(n,MaxValue);
n++;
Write.Console(i.ToString());
}
Запуск линейного конгруэнтного генератора один раз для генерации каждого числа может привести к довольно слабым результатам. Выполнение этого через ряд итераций, которые относительно просты для вашей базы (100 000 000 в данном случае), значительно улучшит ее. Если, прежде чем сообщать о каждом выходе генератора, вы запускаете его с помощью одной или нескольких дополнительных функций перестановки, конечный результат по-прежнему будет перестановкой без дубликатов столько чисел, сколько вы хотите (до 100 000 000), но если выбраны правильные функции результат может быть криптографически сильным.
Мне нравится решение Lazarus, но если вы хотите избежать эффективного предварительного выделения места для каждого возможного числа, просто сохраните использованные числа в таблице, но создайте список «неиспользуемых чисел» в памяти, добавив все возможные числа в коллекция затем удаляет все, что присутствует в базе данных. Затем выберите одно из оставшихся чисел и используйте его, очевидно, добавив его в список в базе данных.
Но, как я уже сказал, мне нравится решение Лазару - я думаю, что это ваш лучший выбор для большинства сценариев.
Вы можете попробовать ввести имена пользователей, используя начальный номер и дополнительный номер. Вы начинаете с числа (скажем, 12000), затем для каждой созданной учетной записи число увеличивается на возрастающее значение.
id = startValue + (totalNumberOfAccounts * inctrementalNumber)
Если incrementalNumber - простое значение, вы должны быть в состоянии циклически обойти максимальное значение учетной записи и не задавать другое значение. Это создает иллюзию случайного идентификатора, но также должно иметь очень мало конфликтов. В случае конфликтов, вы можете добавить число, чтобы увеличить, когда есть конфликт, поэтому приведенный выше код становится. Мы хотим разобраться с этим случаем, поскольку, если мы столкнемся с одним значением учетной записи, которое будет идентичным, при увеличении мы столкнемся с другим конфликтом при следующем увеличении.
id = startValue + (totalNumberOfAccounts * inctrementalNumber) + totalConflicts
Вы можете просто разместить свои номера в наборе. Если размер набора после генерации ваших N чисел слишком мал, сгенерируйте еще немного.
Сделайте несколько пробных заездов. Сколько чисел вам нужно сгенерировать в среднем? Постарайтесь найти оптимальное решение для компромисса «генерируйте слишком много чисел» / «слишком часто проверяйте наличие дубликатов». Оптимальным является число M, так что после генерации M номеров ваш набор, скорее всего, будет содержать N уникальных чисел.
Да, и M также можно рассчитать: если вам нужно дополнительное число (ваш набор содержит N-1), то вероятность того, что случайное число уже будет в наборе, составляет (N-1) / R, с R быть диапазон. Здесь я пойду в раздумье, так что вам придётся самим в этом разобраться (но такие вещи делают программирование увлекательным, нет?).
Для крайне ограниченного размера ваших чисел нет, вы не можете ожидать уникальности для любого типа случайного поколения.
Вы генерируете 32-битное целое число, в то время как для достижения уникальности вам нужно гораздо большее число в терминах около 128-бит, то есть размер GUID, который гарантированно всегда будет глобально уникальным.
Вы можете наложить уникальное ограничение на столбец, который содержит случайное число, а затем обработать любые колебания ограничения путем регенерации числа. Я думаю, что это обычно индексирует столбец, так что это будет быстрее.
Вы пометили вопрос с помощью C #, поэтому я предполагаю, что вы используете C # для генерации случайного числа. Возможно, подумайте о том, чтобы заставить базу данных генерировать случайное число в хранимой процедуре и вернуть его.
Вы можете использовать либо линейный конгруэнтный генератор (LCG), либо регистр сдвига с линейной обратной связью (LFSR). Google или Википедия для получения дополнительной информации.
Оба могут, с правильными параметрами, работать на основе «полного цикла» (или «полного периода»), так что они будут генерировать «псевдослучайное число» только один раз за один период, и генерировать все числа в диапазоне. Оба являются «слабыми» генераторами, поэтому не годятся для цитографии, но, возможно, «достаточно хороши» для очевидной случайности. Возможно, вам придется ограничить период для работы в пределах вашего «десятичного» максимума, поскольку наличие «двоичных» периодов необходимо.
Обновление: я должен добавить, что нет необходимости предварительно рассчитывать или предварительно сохранять предыдущие значения каким-либо образом, вам нужно только сохранить предыдущее начальное значение (single int) и вычислить «по требованию» следующее номер в последовательности. Конечно, вы можете при желании сохранить цепочку предварительно рассчитанных чисел в вашей БД, но в этом нет необходимости.