Próbuję uzyskać liczby losowe z zakresu od 0 do 100. Ale chcę, aby były unikalne, a nie powtarzane w sekwencji. Na przykład, jeśli mam 5 liczb, powinny to być 82,12,53,64,32, a nie 82,12,53,12,32. Użyłem tego, ale generuje te same liczby w sekwencji.
Random rand = new Random();
selected = rand.nextInt(100);
1..100
(są do tego znane algorytmy), ale zatrzymaj się po określeniu pierwszychn
elementów.Odpowiedzi:
Oto prosta implementacja. Spowoduje to wydrukowanie 3 unikalnych liczb losowych z zakresu 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)); } } }
Pierwsza część poprawki z oryginalnym podejściem, jak wskazał Mark Byers w usuniętej odpowiedzi, polega na użyciu tylko jednej
Random
instancji.To właśnie powoduje, że liczby są identyczne. Wystąpienie
Random
jest zapełniane przez bieżący czas w milisekundach. Dla określonej wartości początkowej instancja „losowa” zwróci dokładnie tę samą sekwencję liczb pseudolosowych .Pierwszą pętlę for można po prostu zmienić na:
for (int i = 1; i < 11; i++) { list.add(i); }
źródło
W Javie 8+ możesz użyć
ints
metody,Random
aby uzyskaćIntStream
losowe wartościdistinct
ilimit
zredukować strumień do wielu unikalnych losowych wartości.ThreadLocalRandom.current().ints(0, 100).distinct().limit(5).forEach(System.out::println);
Random
ma również metody, które tworząLongStream
s iDoubleStream
s, jeśli ich potrzebujesz.Jeśli chcesz wszystkie (lub dużą liczbę) liczb w zakresie w kolejności losowej, bardziej wydajne może być dodanie wszystkich liczb do listy, przetasowanie ich i pobranie pierwszego n, ponieważ powyższy przykład jest obecnie zaimplementowany generując liczby losowe z żądanego zakresu i przepuszczając je przez zbiór (podobnie jak w przypadku odpowiedzi Roba Kielty'ego ), co może wymagać wygenerowania o wiele więcej niż kwota przekazana do limitu, ponieważ prawdopodobieństwo wygenerowania nowej unikalnej liczby maleje wraz z każdym znalezionym. Oto przykład innego sposobu:
List<Integer> range = IntStream.range(0, 100).boxed() .collect(Collectors.toCollection(ArrayList::new)); Collections.shuffle(range); range.subList(0, 99).forEach(System.out::println);
źródło
Arrays#setAll()
jest trochę szybszy niż strumień. A więc: `Integer [] indeksy = new Integer [n]; Arrays.setAll (indeksy, i -> i); Collections.shuffle (Arrays.asList (indeksy)); return Arrays.stream (indeksy) .mapToInt (Integer :: intValue) .toArray (); `long
której przesuwasz i maskujesz, aby uzyskać dostęp do poszczególnych bitów).źródło
pick()
jest przykładem.HashSet
, gdzie przechowujesz już wygenerowane liczby i używaszcontains
do sprawdzenia, czy już wygenerowałeś tę liczbę.HashSet
Prawdopodobnie będzie nieco wolniejszy niż logicznej tablicy, ale zajmują mniej miejsca w pamięci.Użyj
Collections.shuffle()
na wszystkich 100 liczbach i wybierz pierwsze pięć, jak pokazano tutaj .źródło
Uważam, że warto wspomnieć o tej metodzie.
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; }
źródło
Ponownie rozlokowałem odpowiedź Ananda, aby wykorzystać nie tylko unikalne właściwości zestawu, ale także użyć wartości logicznej false zwracanej przez,
set.add()
gdy dodanie do zestawu nie powiedzie się.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); } }
źródło
SET_SIZE_REQUIRED
jest wystarczająco duży (powiedzmy, więcej niżNUMBER_RANGE / 2
wtedy, masz znacznie większy oczekiwany czas pracy.Zrobiłem to w ten sposób.
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); } }
źródło
To zadziała w celu wygenerowania unikalnych liczb losowych ................
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); } }
źródło
Sprytnym sposobem na to jest użycie wykładników elementu pierwotnego w module.
Na przykład 2 to prymitywny rdzeń mod 101, co oznacza, że potęgi 2 mod 101 dają niepowtarzalną sekwencję, która widzi każdą liczbę od 1 do 100 włącznie:
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
W kodzie Java napisałbyś:
void randInts() { int num=1; for (int ii=0; ii<101; ii++) { System.out.println(num); num= (num*2) % 101; } }
Znalezienie prymitywnego korzenia dla określonego modułu może być trudne, ale funkcja „primroot” Maple'a zrobi to za Ciebie.
źródło
Przyszedłem tutaj z innego pytania, które było duplikatem tego pytania ( Generowanie unikalnej liczby losowej w java )
Przechowuj od 1 do 100 liczb w tablicy.
Wygeneruj liczbę losową z przedziału od 1 do 100 jako pozycję i zwróć tablicę [pozycja-1], aby uzyskać wartość
Gdy użyjesz liczby w tablicy, oznacz wartość jako -1 (nie ma potrzeby utrzymywania innej tablicy, aby sprawdzić, czy ta liczba jest już używana)
Jeśli wartością w tablicy jest -1, pobierz losową liczbę ponownie, aby pobrać nową lokalizację w tablicy.
źródło
Mam proste rozwiązanie tego problemu, dzięki temu możemy łatwo wygenerować n liczby unikalnych liczb losowych, to po prostu logika, którą każdy może używać w dowolnym języku.
for(int i=0;i<4;i++) { rn[i]= GenerateRandomNumber(); for (int j=0;j<i;j++) { if (rn[i] == rn[j]) { i--; } } }
źródło
break;
poi—;
wypróbuj to
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); } }
źródło
Nie różni się to znacząco od innych odpowiedzi, ale na końcu chciałem mieć tablicę liczb całkowitych:
Integer[] indices = new Integer[n]; Arrays.setAll(indices, i -> i); Collections.shuffle(Arrays.asList(indices)); return Arrays.stream(indices).mapToInt(Integer::intValue).toArray();
źródło
możesz użyć tablicy boolowskiej, aby wypełnić prawdę, jeśli wartość została pobrana w przeciwnym razie ustaw nawigację po tablicy boolowskiej, aby uzyskać wartość zgodnie z poniższym
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; } } }
źródło
Wybierz n niepowtarzalnych liczb losowych od 0 do 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; }
Wyobraź sobie listę zawierającą liczby od 0 do m-1. Aby wybrać pierwszą liczbę, po prostu używamy
rand.nextInt(m)
. Następnie usuń numer z listy. Teraz pozostaje liczba m-1, więc dzwonimyrand.nextInt(m-1)
. Otrzymana przez nas liczba reprezentuje pozycję na liście. Jeśli jest mniejsza niż pierwsza liczba, to jest to druga liczba, ponieważ część listy poprzedzająca pierwszą liczbę nie została zmieniona przez usunięcie pierwszej liczby. Jeśli pozycja jest większa lub równa pierwszej liczbie, druga liczba to pozycja + 1. Wykonaj dalsze wyprowadzenie, możesz uzyskać ten algorytm.Wyjaśnienie
Ten algorytm ma złożoność O (n ^ 2). Jest więc dobry do generowania małej ilości unikalnych liczb z dużego zbioru. Podczas gdy algorytm oparty na tasowaniu potrzebuje co najmniej O (m), aby wykonać shuffle.
Również algorytm oparty na tasowaniu potrzebuje pamięci do przechowywania każdego możliwego wyniku, aby wykonać tasowanie, ten algorytm nie potrzebuje.
źródło
Możesz użyć klasy Collections.
Klasa narzędziowa o nazwie Kolekcje oferuje różne akcje, które można wykonać na kolekcji, takiej jak ArrayList (np. Przeszukiwanie elementów, znajdowanie elementu maksymalnego lub minimalnego, odwracanie kolejności elementów itd.). Jedną z czynności, które może wykonać, jest tasowanie elementów. Tasowanie spowoduje losowe przeniesienie każdego elementu na inne miejsce na liście. Robi to za pomocą obiektu Random. Oznacza to, że jest to deterministyczna losowość, ale w większości sytuacji wystarczy.
Aby przetasować ArrayList, dodaj import kolekcji na początku programu, a następnie użyj statycznej metody Shuffle. Wymaga tasowania ArrayList jako parametru:
import java.util.Collections; import java.util.ArrayList; public class Lottery { public static void main(String[] args) { //define ArrayList to hold Integer objects ArrayList numbers = new ArrayList(); for(int i = 0; i < 100; i++) { numbers.add(i+1); } Collections.shuffle(numbers); System.out.println(numbers); } }
źródło
Chociaż to stary wątek, ale dodanie innej opcji może nie zaszkodzić. (Funkcje lambda JDK 1.8 wydają się to ułatwiać);
Problem można podzielić na następujące kroki;
Oto funkcja z pewnym opisem:
/** * Provided an unsequenced / sequenced list of integers, the function returns unique random IDs as defined by the parameter * @param numberToGenerate * @param idList * @return List of unique random integer values from the provided list */ private List<Integer> getUniqueRandomInts(List<Integer> idList, Integer numberToGenerate) { List<Integer> generatedUniqueIds = new ArrayList<>(); Integer minId = idList.stream().mapToInt (v->v).min().orElseThrow(NoSuchElementException::new); Integer maxId = idList.stream().mapToInt (v->v).max().orElseThrow(NoSuchElementException::new); ThreadLocalRandom.current().ints(minId,maxId) .filter(e->idList.contains(e)) .distinct() .limit(numberToGenerate) .forEach(generatedUniqueIds:: add); return generatedUniqueIds; }
Aby uzyskać 11 unikalnych liczb losowych dla obiektu listy „allIntegers”, wywołamy funkcję w następujący sposób;
List<Integer> ids = getUniqueRandomInts(allIntegers,11);
Funkcja deklaruje new arrayList „generatedUniqueIds” i przed zwróceniem wypełnia każdą unikalną losową liczbę całkowitą do wymaganej liczby.
Klasa PS ThreadLocalRandom unika wspólnej wartości inicjatora w przypadku współbieżnych wątków.
źródło
Jest to najprostsza metoda generowania unikatowych wartości losowych w zakresie lub z tablicy .
W tym przykładzie będę używał predefiniowanej tablicy, ale możesz dostosować tę metodę również do generowania liczb losowych. Najpierw utworzymy przykładową tablicę, z której będą pobierane nasze dane.
ArrayList<Integer> sampleList = new ArrayList<>(); sampleList.add(1); sampleList.add(2); sampleList.add(3); sampleList.add(4); sampleList.add(5); sampleList.add(6); sampleList.add(7); sampleList.add(8);
Teraz
sampleList
stworzymy pięć liczb losowych, które są niepowtarzalne.int n; randomList = new ArrayList<>(); for(int i=0;i<5;i++){ Random random = new Random(); n=random.nextInt(8); //Generate a random index between 0-7 if(!randomList.contains(sampleList.get(n))) randomList.add(sampleList.get(n)); else i--; //reiterating the step }
Jest to koncepcyjnie bardzo proste. Jeśli wygenerowana wartość losowa już istnieje, powtórzymy krok. Będzie to trwało, dopóki wszystkie wygenerowane wartości nie będą unikalne.
Jeśli uznasz tę odpowiedź za przydatną, możesz ją zagłosować, ponieważ jest o wiele prosta w koncepcji w porównaniu z innymi odpowiedziami .
źródło
W Javie możesz wygenerować n niepowtarzalnych liczb losowych z zakresu od 0 do n-1
public static void RandomGenerate(int n) { Set<Integer> st=new HashSet<Integer>(); Random r=new Random(); while(st.size()<n) { st.add(r.nextInt(n)); }
}
źródło
Sprawdź to
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; } }
źródło
Poniżej znajduje się sposób, w jaki zawsze generowałem unikalny numer. Funkcja losowa generuje liczbę i przechowuje ją w pliku tekstowym, a następnym razem, gdy sprawdza ją w pliku, porównuje ją i generuje nowy unikalny numer, w ten sposób zawsze jest nowy unikalny numer.
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; }
źródło