2012-03-04 2 views
2

У меня есть простой код, который генерирует случайные числаКак быть уверенным, что случайные числа уникальны и не дублируются?

SecureRandom random = new SecureRandom(); 
... 
public int getRandomNumber(int maxValue) { 
    return random.nextInt(maxValue); 
} 

Метод выше, называется примерно в 10 раз (не в цикле). Я хочу, чтобы все числа были уникальными (при условии, что maxValue > 1000).

Могу ли я быть уверенным, что получаю уникальные номера каждый раз, когда я его называю? Если нет, как я могу это исправить?

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

+10

Random! = Уникальный. На самом деле, как раз наоборот. –

+1

Либо проверьте номера для предыдущего использования перед их выпуском, либо используйте случайный * случайный * случайный номер. Последний переполнен, если вы получаете только 10 номеров. Второй ответ Оли выше, хотя у вас есть две проблемы - случайность и уникальность. –

+0

Отредактировал вопрос, чтобы прояснить терминологию уникальных vs random – skaffman

ответ

5

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

  • Если вы выбираете небольшое количество случайных чисел из большого числа потенциальных номеров, то вам, вероятно, лучше всего хранить ранее выбранные числа в наборе и «вручную» проверять дубликаты. Большую часть времени вы фактически не получите дубликат, и тест практически будет практически нулевым. Это может звучать неэлегантно, но на самом деле это не так плохо, как кажется.
  • Некоторые алгоритмы генерации случайных чисел не генерируют дубликаты на их «исходном» уровне. Так, например, алгоритм, называемый генератором XORShift, может эффективно производить все числа в определенном диапазоне, перетасованные без дубликатов. Таким образом, вы в основном выбираете случайную начальную точку в последовательности, а затем генерируете следующие n чисел, и вы знаете, что дубликатов не будет. Но вы не можете произвольно выбрать «max» в этом случае: он должен быть естественным максимумом генератора, о котором идет речь.
  • Если диапазон возможных чисел мал-иш, но количество чисел, которое вам нужно выбрать, находится в пределах нескольких порядков величины этого диапазона, тогда вы можете рассматривать это как случайный выбор .Например, чтобы выбрать 100000 номеров в пределах диапазона 10000000 без дублей, я могу это сделать:

    Пусть т число случайных чисел, я выбрал до сих пор

    Для я = 1 10000000

    Создание случайного (с плавающей точкой) число, г, в диапазоне 0-1

    Если (г < (100000-м)/(10000000-я)), а затем добавить I в список и приращение m

    Перемешать список, а затем выбрать номера последовательно из списка в соответствии с требованиями

Но, очевидно, есть только много смысла в выборе последнего варианта, если вам нужно выбрать какой-то достаточно большая часть общий диапазон чисел. Для выбора 10 номеров в диапазоне от 1 до миллиарда вы будете генерировать миллиард случайных чисел, когда, просто проверяя дубликаты, когда вы идете, вы вряд ли действительно получите дубликат и только закончили бы создание 10 случайных чисел номера.

+0

Действительно полезно. XORShift выглядит интересным. спасибо – user219882

1

Случайная последовательность не означает, что все значения уникальны. Последовательность 1,1,1,1 точно такая же, как последовательность 712,4,22,424.

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

0

Для такого небольшого числа возможных значений тривиальная реализация должна заключаться в том, чтобы поместить ваши 1000 целых чисел в список и иметь цикл, который на каждой итерации генерирует случайное число между 0 и list.size(), выбирает номер, сохраненный по этому индексу и удалите его из списка.

+0

Я следую вашим ответам и многому научился, что вы такой вкладчик. Разве 1000 целых списков и поиск уже сгенерированных чисел дорогостоящим? – kosa

+0

все зависит от того, сколько раз это называется, при каких обстоятельствах и т. Д. Если сделать это в узком цикле, называемом миллиардом раз, было бы полезно выбрать лучший подход. Если это нужно сделать один или два раза или в приложении, где большую часть времени тратится на вход пользователя, вам все равно. (PS: Я не знал, что у меня был фанат ;-)) –

+0

Ваш анализ и ответы заслуживают поклонников. ха-ха !. Я отвечаю, но мои ответы останавливаются на A-G, ваши ответы охватывают полную базу A-Z. Всего наилучшего. – kosa

1

Каждый раз, когда вы звоните Random#nextInt(int) вы получите

псевдослучайный, равномерно распределенное значение INT между 0 (включительно) и заданным значением (исключительным).

Если вы хотите x уникальных номеров, продолжайте получать новые номера, пока у вас их не будет, а затем выберите свой «случайный» номер из этого списка. Однако, поскольку вы фильтруете генерируемые числа, они больше не будут случайными.

0

Это код очень эффективен с процессором за счет стоимости памяти. Стоимость каждого потенциального значения sizeof(int) * maxValue. Целое число без знака будет работать до 65535 как максимум. long можно использовать за счет большого количества памяти 2000 байт для 1000 значений 16-битных целых чисел.

Вся цель массива сказать, вы использовали это значение до или не 1 = yes «что-нибудь еще = нет » Цикла, пока будет держать генерации случайных чисел, пока уникальное значение не найдено. 'после того, как найдено хорошее случайное значение, оно помечает его как использовано, а затем возвращает его. «Будьте осторожны с областью действия переменной a, как будто она выходит из области видимости, которую может удалить ваш массив. «Я использовал это в c, и он работает. 'может занять немного времени, чтобы заставить его работать на Java.

unsigned int a(1000); 

public int getRandomNumber(int maxValue) { 
    unsigned int rand; 

    while(a(rand)==1) { 
    rand=random.nextInt(maxValue); 
    if (a(rand)!=1) { a(rand)=1; return rand;} 
    } 

} 
Смежные вопросы