Генерация уникальных случайных чисел в Java
Я пытаюсь получить случайные числа между 0 и 100. Но я хочу, чтобы они были уникальными, а не повторялись в последовательности. Например, если я получил 5 чисел, они должны быть 82,12,53,64,32, а не 82,12,53,12,32
Я использовал это, но он генерирует те же числа в последовательности.
Random rand = new Random();
selected = rand.nextInt(100);
16 ответов:
- добавить каждое число в диапазоне последовательно в список структура.
- перетасовка его.
- Возьмите первый 'n'.
вот простая реализация. Это выведет 3 уникальных случайных числа из диапазона 1-10.
import java.util.ArrayList; import java.util.Collections; public class UniqueRandomNumbers { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<Integer>(); for (int i=1; i<11; i++) { list.add(new Integer(i)); } Collections.shuffle(list); for (int i=0; i<3; i++) { System.out.println(list.get(i)); } } }
первая часть исправления с оригинальным подходом, как отметил Марк Байерс в ответе, который теперь удален, заключается в использовании только одного
Randomэкземпляра.это то, что заставляет числа быть идентичными. А
Randomэкземпляр заполняется текущим временем в миллисекундах. Для конкретного начальное значение, "случайный" экземпляр вернет то же самое последовательность псевдослучайных цифры.
С Java 8+ вы можете использовать
intsметодRandomдля полученияIntStreamслучайных величин тогдаdistinctиlimitчтобы уменьшить поток до нескольких уникальных случайных значений.ThreadLocalRandom.current().ints(0, 100).distinct().limit(5).forEach(System.out::println);
Randomтакже есть методы, которые создаютLongStreams иDoubleStreams, Если вам это нужно вместо этого.если вы хотите, чтобы все (или большое количество) чисел в диапазоне в случайном порядке это может быть больше эффективно добавить все числа в список, перетасовать его и взять первый n, потому что приведенный выше пример в настоящее время реализуется путем генерации случайных чисел в запрошенном диапазоне и передачи их через набор (аналогично ответ Роба Кьелти), что может потребовать генерации намного больше, чем сумма, переданная для ограничения, потому что вероятность генерации нового уникального числа уменьшается с каждым найденным. Вот пример другого способа:
List<Integer> range = IntStream.range(0, 100).boxed() .collect(Collectors.toCollection(ArrayList::new)); Collections.shuffle(range); range.subList(0, 99).forEach(System.out::println);
- создать массив из 100 чисел, а затем перемешивать их порядок.
- разработать генератор псевдослучайных чисел, который имеет диапазон 100.
- создать логический массив из 100 элементов, а затем установить элемент true, когда вы выбираете это число. При выборе следующего номера проверьте массив и повторите попытку, если элемент массива установлен. (Вы можете сделать простой в очистке логический массив с массивом
longгде вы сдвигаете и маску для доступа к отдельным биты.)
использовать
Collections.shuffle()на все 100 чисел и выберите первые пять, как показано здесь.
Я чувствую, что этот метод стоит упомянуть.
private static final Random RANDOM = new Random(); /** * Pick n numbers between 0 (inclusive) and k (inclusive) * While there are very deterministic ways to do this, * for large k and small n, this could be easier than creating * an large array and sorting, i.e. k = 10,000 */ public Set<Integer> pickRandom(int n, int k) { final Set<Integer> picked = new HashSet<>(); while (picked.size() < n) { picked.add(RANDOM.nextInt(k + 1)); } return picked; }
Я пересмотрел ответ Ананда, чтобы использовать не только уникальные свойства набора, но и использовать логическое значение false, возвращаемое
set.add()при сбое добавления к набору.import java.util.HashSet; import java.util.Random; import java.util.Set; public class randomUniqueNumberGenerator { public static final int SET_SIZE_REQUIRED = 10; public static final int NUMBER_RANGE = 100; public static void main(String[] args) { Random random = new Random(); Set set = new HashSet<Integer>(SET_SIZE_REQUIRED); while(set.size()< SET_SIZE_REQUIRED) { while (set.add(random.nextInt(NUMBER_RANGE)) != true) ; } assert set.size() == SET_SIZE_REQUIRED; System.out.println(set); } }
Это будет работать для генерации уникальных случайных чисел................
import java.util.HashSet; import java.util.Random; public class RandomExample { public static void main(String[] args) { Random rand = new Random(); int e; int i; int g = 10; HashSet<Integer> randomNumbers = new HashSet<Integer>(); for (i = 0; i < g; i++) { e = rand.nextInt(20); randomNumbers.add(e); if (randomNumbers.size() <= 10) { if (randomNumbers.size() == 10) { g = 10; } g++; randomNumbers.add(e); } } System.out.println("Ten Unique random numbers from 1 to 20 are : " + randomNumbers); } }
Я пришел сюда из другого вопроса, который был дубликатом этого вопроса ( генерация уникального случайного числа в java)
хранить от 1 до 100 чисел в массиве.
генерировать случайное число от 1 до 100, как положение и вернуть массив[Позиция 1], чтобы получить значение
Как только вы используете число в массиве, отметьте значение как -1 ( нет необходимости поддерживать другой массив, чтобы проверить, если это число уже используется)
Если значение в массиве равно -1, получить случайное число снова, чтобы получить новое местоположение в массиве.
Я сделал это так.
Random random = new Random(); ArrayList<Integer> arrayList = new ArrayList<Integer>(); while (arrayList.size() < 6) { // how many numbers u need - it will 6 int a = random.nextInt(49)+1; // this will give numbers between 1 and 50. if (!arrayList.contains(a)) { arrayList.add(a); } }
например, 2-это примитивный корневой мод 101, что означает, что полномочия 2 Мод 101 дают вам неповторяющуюся последовательность, которая видит каждое число от 1 до 100 включительно:
2^0 mod 101 = 1 2^1 mod 101 = 2 2^2 mod 101 = 4 ... 2^50 mod 101 = 100 2^51 mod 101 = 99 2^52 mod 101 = 97 ... 2^100 mod 101 = 1в коде Java вы бы написали:
void randInts() { int num=1; for (int ii=0; ii<101; ii++) { System.out.println(num); num= (num*2) % 101; } }найти примитивный корень для определенного модуля может быть сложно, но функция Maple "primroot" сделает это за вас.
попробуйте это
public class RandomValueGenerator { /** * */ private volatile List<Double> previousGenValues = new ArrayList<Double>(); public void init() { previousGenValues.add(Double.valueOf(0)); } public String getNextValue() { Random random = new Random(); double nextValue=0; while(previousGenValues.contains(Double.valueOf(nextValue))) { nextValue = random.nextDouble(); } previousGenValues.add(Double.valueOf(nextValue)); return String.valueOf(nextValue); } }
Это не сильно отличается от других ответов, но я хотел массив целых чисел в конце:
Integer[] indices = new Integer[n]; Arrays.setAll(indices, i -> i); Collections.shuffle(Arrays.asList(indices)); return Arrays.stream(indices).mapToInt(Integer::intValue).toArray();
Ниже приведен способ, который я использовал для создания уникального номера всегда. Случайная функция генерирует число и сохраняет его в текстовом файле, а затем в следующий раз он проверяет его в файле сравнивает его и генерирует новый уникальный номер, следовательно, таким образом, всегда есть новый уникальный номер.
public int GenerateRandomNo() { int _min = 0000; int _max = 9999; Random _rdm = new Random(); return _rdm.Next(_min, _max); } public int rand_num() { randnum = GenerateRandomNo(); string createText = randnum.ToString() + Environment.NewLine; string file_path = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + @"\Invoices\numbers.txt"; File.AppendAllText(file_path, createText); int number = File.ReadLines(file_path).Count(); //count number of lines in file System.IO.StreamReader file = new System.IO.StreamReader(file_path); do { randnum = GenerateRandomNo(); } while ((file.ReadLine()) == randnum.ToString()); file.Close(); return randnum; }
вы можете использовать логический массив для заполнения true если значение взято еще установить перейдите через логический массив, чтобы получить значение, как указано ниже
package study; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /* Created By Sachin Rane on Jul 18, 2018 */ public class UniqueRandomNumber { static Boolean[] boolArray; public static void main(String s[]){ List<Integer> integers = new ArrayList<>(); for (int i = 0; i < 10; i++) { integers.add(i); } //get unique random numbers boolArray = new Boolean[integers.size()+1]; Arrays.fill(boolArray, false); for (int i = 0; i < 10; i++) { System.out.print(getUniqueRandomNumber(integers) + " "); } } private static int getUniqueRandomNumber(List<Integer> integers) { int randNum =(int) (Math.random()*integers.size()); if(boolArray[randNum]){ while(boolArray[randNum]){ randNum++; if(randNum>boolArray.length){ randNum=0; } } boolArray[randNum]=true; return randNum; }else { boolArray[randNum]=true; return randNum; } } }
выберите n уникальных случайных чисел от 0 до m-1.
int[] uniqueRand(int n, int m){ Random rand = new Random(); int[] r = new int[n]; int[] result = new int[n]; for(int i = 0; i < n; i++){ r[i] = rand.nextInt(m-i); result[i] = r[i]; for(int j = i-1; j >= 0; j--){ if(result[i] >= r[j]) result[i]++; } } return result; }представьте себе список, содержащий числа от 0 до M-1. Чтобы выбрать первое число, мы просто использовать
rand.nextInt(m). Затем удалите номер из списка. Теперь остается M-1 чисел, поэтому мы называемrand.nextInt(m-1). Число, которое мы получаем, представляет позицию в списке. Если он меньше первого числа, то это второе число, так как часть списка до первого числа не была изменена путем удаления первого числа. Если позиция больше или равна первому числу, второе число-Позиция+1. Сделайте некоторые дальнейшие выводы, вы можете получить этот алгоритм.
проверить это
public class RandomNumbers { public static void main(String[] args) { // TODO Auto-generated method stub int n = 5; int A[] = uniqueRandomArray(n); for(int i = 0; i<n; i++){ System.out.println(A[i]); } } public static int[] uniqueRandomArray(int n){ int [] A = new int[n]; for(int i = 0; i< A.length; ){ if(i == A.length){ break; } int b = (int)(Math.random() *n) + 1; if(f(A,b) == false){ A[i++] = b; } } return A; } public static boolean f(int[] A, int n){ for(int i=0; i<A.length; i++){ if(A[i] == n){ return true; } } return false; } }
Comments