En este caso, el MAX es solo 5, por lo que podría verificar los duplicados uno por uno, pero ¿cómo podría hacer esto de una manera más simple? Por ejemplo, ¿qué pasa si el MAX tiene un valor de 20? Gracias.
int MAX = 5;
for (i = 1 , i <= MAX; i++)
{
drawNum[1] = (int)(Math.random()*MAX)+1;
while (drawNum[2] == drawNum[1])
{
drawNum[2] = (int)(Math.random()*MAX)+1;
}
while ((drawNum[3] == drawNum[1]) || (drawNum[3] == drawNum[2]) )
{
drawNum[3] = (int)(Math.random()*MAX)+1;
}
while ((drawNum[4] == drawNum[1]) || (drawNum[4] == drawNum[2]) || (drawNum[4] == drawNum[3]) )
{
drawNum[4] = (int)(Math.random()*MAX)+1;
}
while ((drawNum[5] == drawNum[1]) ||
(drawNum[5] == drawNum[2]) ||
(drawNum[5] == drawNum[3]) ||
(drawNum[5] == drawNum[4]) )
{
drawNum[5] = (int)(Math.random()*MAX)+1;
}
}
Respuestas:
La forma más sencilla sería crear una lista de los números posibles (1..20 o lo que sea) y luego mezclarlos con
Collections.shuffle
. Luego, simplemente tome tantos elementos como desee. Esto es genial si tu rango es igual al número de elementos que necesitas al final (por ejemplo, para barajar una baraja de cartas).Eso no funciona tan bien si quieres (digamos) 10 elementos aleatorios en el rango 1..10,000 - terminarías haciendo mucho trabajo innecesariamente. En ese punto, probablemente sea mejor mantener un conjunto de valores que ha generado hasta ahora y seguir generando números en un ciclo hasta que el siguiente no esté ya presente:
if (max < numbersNeeded) { throw new IllegalArgumentException("Can't ask for more numbers than are available"); } Random rng = new Random(); // Ideally just create one instance globally // Note: use LinkedHashSet to maintain insertion order Set<Integer> generated = new LinkedHashSet<Integer>(); while (generated.size() < numbersNeeded) { Integer next = rng.nextInt(max) + 1; // As we're adding to a set, this will automatically do a containment check generated.add(next); }
Sin embargo, tenga cuidado con la elección del conjunto: lo he usado deliberadamente,
LinkedHashSet
ya que mantiene el orden de inserción, lo que nos importa aquí.Otra opción más es progresar siempre , reduciendo el rango cada vez y compensando los valores existentes. Entonces, por ejemplo, suponga que desea 3 valores en el rango 0..9. En la primera iteración, generaría cualquier número en el rango 0..9; digamos que genera un 4.
En la segunda iteración, generaría un número en el rango 0..8. Si el número generado es menor que 4, lo mantendrá como está ... de lo contrario, le agregará uno. Eso le da un rango de resultado de 0..9 sin 4. Suponga que obtenemos 7 de esa manera.
En la tercera iteración, generaría un número en el rango 0..7. Si el número generado es menor que 4, lo mantendrá como está. Si es 4 o 5, agregaría uno. Si es 6 o 7, agregaría dos. De esa manera, el rango de resultados es 0..9 sin 4 o 6.
fuente
Así es como lo haría
import java.util.ArrayList; import java.util.Random; public class Test { public static void main(String[] args) { int size = 20; ArrayList<Integer> list = new ArrayList<Integer>(size); for(int i = 1; i <= size; i++) { list.add(i); } Random rand = new Random(); while(list.size() > 0) { int index = rand.nextInt(list.size()); System.out.println("Selected: "+list.remove(index)); } } }
Como ha señalado el estimado Sr. Skeet:
Si n es el número de números seleccionados al azar que desea elegir y N es el espacio muestral total de números disponibles para la selección:
fuente
//random numbers are 0,1,2,3 ArrayList<Integer> numbers = new ArrayList<Integer>(); Random randomGenerator = new Random(); while (numbers.size() < 4) { int random = randomGenerator .nextInt(4); if (!numbers.contains(random)) { numbers.add(random); } }
fuente
Hay otra forma de hacer números ordenados "aleatorios" con LFSR, eche un vistazo a:
http://en.wikipedia.org/wiki/Linear_feedback_shift_register
con esta técnica puedes conseguir el número aleatorio ordenado por índice y asegurándote de que los valores no estén duplicados.
Pero estos no son números aleatorios VERDADEROS porque la generación aleatoria es determinista.
Pero dependiendo de su caso , puede usar esta técnica para reducir la cantidad de procesamiento en la generación de números aleatorios cuando usa la mezcla.
Aquí un algoritmo LFSR en Java, (lo llevé a algún lugar que no recuerdo):
public final class LFSR { private static final int M = 15; // hard-coded for 15-bits private static final int[] TAPS = {14, 15}; private final boolean[] bits = new boolean[M + 1]; public LFSR() { this((int)System.currentTimeMillis()); } public LFSR(int seed) { for(int i = 0; i < M; i++) { bits[i] = (((1 << i) & seed) >>> i) == 1; } } /* generate a random int uniformly on the interval [-2^31 + 1, 2^31 - 1] */ public short nextShort() { //printBits(); // calculate the integer value from the registers short next = 0; for(int i = 0; i < M; i++) { next |= (bits[i] ? 1 : 0) << i; } // allow for zero without allowing for -2^31 if (next < 0) next++; // calculate the last register from all the preceding bits[M] = false; for(int i = 0; i < TAPS.length; i++) { bits[M] ^= bits[M - TAPS[i]]; } // shift all the registers for(int i = 0; i < M; i++) { bits[i] = bits[i + 1]; } return next; } /** returns random double uniformly over [0, 1) */ public double nextDouble() { return ((nextShort() / (Integer.MAX_VALUE + 1.0)) + 1.0) / 2.0; } /** returns random boolean */ public boolean nextBoolean() { return nextShort() >= 0; } public void printBits() { System.out.print(bits[M] ? 1 : 0); System.out.print(" -> "); for(int i = M - 1; i >= 0; i--) { System.out.print(bits[i] ? 1 : 0); } System.out.println(); } public static void main(String[] args) { LFSR rng = new LFSR(); Vector<Short> vec = new Vector<Short>(); for(int i = 0; i <= 32766; i++) { short next = rng.nextShort(); // just testing/asserting to make // sure the number doesn't repeat on a given list if (vec.contains(next)) throw new RuntimeException("Index repeat: " + i); vec.add(next); System.out.println(next); } } }
fuente
Otro enfoque que le permite especificar con cuántos números desea
size
y los valoresmin
ymax
de los números devueltospublic static int getRandomInt(int min, int max) { Random random = new Random(); return random.nextInt((max - min) + 1) + min; } public static ArrayList<Integer> getRandomNonRepeatingIntegers(int size, int min, int max) { ArrayList<Integer> numbers = new ArrayList<Integer>(); while (numbers.size() < size) { int random = getRandomInt(min, max); if (!numbers.contains(random)) { numbers.add(random); } } return numbers; }
Para usarlo devuelve 7 números entre 0 y 25.
ArrayList<Integer> list = getRandomNonRepeatingIntegers(7, 0, 25); for (int i = 0; i < list.size(); i++) { System.out.println("" + list.get(i)); }
fuente
Esto sería mucho más sencillo en
java-8
:Stream.generate(new Random()::ints) .distinct() .limit(16) // whatever limit you might need .toArray(Integer[]::new);
fuente
La forma más eficiente y básica de tener números aleatorios no repetidos se explica mediante este pseudocódigo. No es necesario tener bucles anidados o búsquedas hash:
// get 5 unique random numbers, possible values 0 - 19 // (assume desired number of selections < number of choices) const int POOL_SIZE = 20; const int VAL_COUNT = 5; declare Array mapping[POOL_SIZE]; declare Array results[VAL_COUNT]; declare i int; declare r int; declare max_rand int; // create mapping array for (i=0; i<POOL_SIZE; i++) { mapping[i] = i; } max_rand = POOL_SIZE-1; // start loop searching for maximum value (19) for (i=0; i<VAL_COUNT; i++) { r = Random(0, max_rand); // get random number results[i] = mapping[r]; // grab number from map array mapping[r] = max_rand; // place item past range at selected location max_rand = max_rand - 1; // reduce random scope by 1 }
Suponga que la primera iteración generó el número aleatorio 3 para comenzar (de 0 a 19). Esto haría que los resultados [0] = mapeo [3], es decir, el valor 3. Luego asignaríamos el mapeo [3] a 19.
En la siguiente iteración, el número aleatorio fue 5 (de 0 a 18). Esto haría que los resultados [1] = mapeo [5], es decir, el valor 5. Luego asignaríamos el mapeo [5] a 18.
Ahora suponga que la siguiente iteración elige 3 nuevamente (de 0 a 17). A los resultados [2] se les asignaría el valor de mapeo [3], pero ahora, este valor no es 3, sino 19.
Esta misma protección persiste para todos los números, incluso si obtuvo el mismo número 5 veces seguidas. Por ejemplo, si el generador de números aleatorios le dio 0 cinco veces seguidas, los resultados serían: [0, 19, 18, 17, 16].
Nunca obtendrías el mismo número dos veces.
fuente
Generar todos los índices de una secuencia es generalmente una mala idea, ya que puede llevar mucho tiempo, especialmente si la proporción de los números a elegir
MAX
es baja (la complejidad se vuelve dominada porO(MAX)
). Esto empeora si la relación de los números a elegir seMAX
acerca a uno, ya que entonces eliminar los índices elegidos de la secuencia de todos también se vuelve costoso (nos acercamosO(MAX^2/2)
). Pero para números pequeños, esto generalmente funciona bien y no es particularmente propenso a errores.Filtrar los índices generados mediante el uso de una colección también es una mala idea, ya que se dedica algo de tiempo a insertar los índices en la secuencia, y el progreso no está garantizado ya que se puede extraer el mismo número aleatorio varias veces (pero para lo suficientemente grande
MAX
es poco probable ). Esto podría estar cerca de la complejidadO(k n log^2(n)/2)
, ignorando los duplicados y asumiendo que la colección usa un árbol para una búsqueda eficiente (pero con un costo constante significativok
de asignar los nodos del árbol y posiblemente tener que reequilibrar ).Otra opción es generar los valores aleatorios de forma única desde el principio, garantizando que se avanza. Eso significa que en la primera ronda,
[0, MAX]
se genera un índice aleatorio en :items i0 i1 i2 i3 i4 i5 i6 (total 7 items) idx 0 ^^ (index 2)
En la segunda ronda, solo
[0, MAX - 1]
se genera (ya que un elemento ya estaba seleccionado):items i0 i1 i3 i4 i5 i6 (total 6 items) idx 1 ^^ (index 2 out of these 6, but 3 out of the original 7)
Luego, los valores de los índices deben ajustarse: si el segundo índice cae en la segunda mitad de la secuencia (después del primer índice), debe incrementarse para tener en cuenta la brecha. Podemos implementar esto como un bucle, lo que nos permite seleccionar un número arbitrario de elementos únicos.
Para secuencias cortas, este es un
O(n^2/2)
algoritmo bastante rápido :void RandomUniqueSequence(std::vector<int> &rand_num, const size_t n_select_num, const size_t n_item_num) { assert(n_select_num <= n_item_num); rand_num.clear(); // !! // b1: 3187.000 msec (the fastest) // b2: 3734.000 msec for(size_t i = 0; i < n_select_num; ++ i) { int n = n_Rand(n_item_num - i - 1); // get a random number size_t n_where = i; for(size_t j = 0; j < i; ++ j) { if(n + j < rand_num[j]) { n_where = j; break; } } // see where it should be inserted rand_num.insert(rand_num.begin() + n_where, 1, n + n_where); // insert it in the list, maintain a sorted sequence } // tier 1 - use comparison with offset instead of increment }
¿Dónde
n_select_num
está tu 5 yn_number_num
es tuMAX
. Losn_Rand(x)
rendimientos enteros aleatorios en[0, x]
(ambos inclusive). Esto se puede hacer un poco más rápido si se seleccionan muchos elementos (por ejemplo, no 5 sino 500) mediante la búsqueda binaria para encontrar el punto de inserción. Para hacer eso, debemos asegurarnos de cumplir con los requisitos.Haremos una búsqueda binaria con la comparación
n + j < rand_num[j]
que es igual an < rand_num[j] - j
. Necesitamos mostrar querand_num[j] - j
sigue siendo una secuencia ordenada para una secuencia ordenadarand_num[j]
. Afortunadamente, esto se muestra fácilmente, ya que la distancia más baja entre dos elementos del originalrand_num
es uno (los números generados son únicos, por lo que siempre hay una diferencia de al menos 1). Al mismo tiempo, si restamos los índicesj
de todos los elementosrand_num[j]
, las diferencias en el índice son exactamente 1. Entonces, en el "peor" caso, obtenemos una secuencia constante, pero nunca decreciente. Por lo tanto, se puede utilizar la búsqueda binaria, dando como resultado elO(n log(n))
algoritmo:struct TNeedle { // in the comparison operator we need to make clear which argument is the needle and which is already in the list; we do that using the type system. int n; TNeedle(int _n) :n(_n) {} }; class CCompareWithOffset { // custom comparison "n < rand_num[j] - j" protected: std::vector<int>::iterator m_p_begin_it; public: CCompareWithOffset(std::vector<int>::iterator p_begin_it) :m_p_begin_it(p_begin_it) {} bool operator ()(const int &r_value, TNeedle n) const { size_t n_index = &r_value - &*m_p_begin_it; // calculate index in the array return r_value < n.n + n_index; // or r_value - n_index < n.n } bool operator ()(TNeedle n, const int &r_value) const { size_t n_index = &r_value - &*m_p_begin_it; // calculate index in the array return n.n + n_index < r_value; // or n.n < r_value - n_index } };
Y finalmente:
void RandomUniqueSequence(std::vector<int> &rand_num, const size_t n_select_num, const size_t n_item_num) { assert(n_select_num <= n_item_num); rand_num.clear(); // !! // b1: 3578.000 msec // b2: 1703.000 msec (the fastest) for(size_t i = 0; i < n_select_num; ++ i) { int n = n_Rand(n_item_num - i - 1); // get a random number std::vector<int>::iterator p_where_it = std::upper_bound(rand_num.begin(), rand_num.end(), TNeedle(n), CCompareWithOffset(rand_num.begin())); // see where it should be inserted rand_num.insert(p_where_it, 1, n + p_where_it - rand_num.begin()); // insert it in the list, maintain a sorted sequence } // tier 4 - use binary search }
He probado esto en tres puntos de referencia. Primero, se eligieron 3 números de 7 elementos, y se acumuló un histograma de los elementos elegidos en más de 10,000 ejecuciones:
4265 4229 4351 4267 4267 4364 4257
Esto muestra que cada uno de los 7 elementos se eligió aproximadamente el mismo número de veces, y no existe un sesgo aparente causado por el algoritmo. También se verificó la exactitud de todas las secuencias (unicidad de los contenidos).
El segundo punto de referencia consistió en elegir 7 números de 5000 elementos. El tiempo de varias versiones del algoritmo se acumuló en 10,000,000 ejecuciones. Los resultados se indican en los comentarios del código como
b1
. La versión simple del algoritmo es un poco más rápida.El tercer punto de referencia consistió en elegir 700 números de 5000 elementos. El tiempo de varias versiones del algoritmo se acumuló nuevamente, esta vez más de 10,000 ejecuciones. Los resultados se indican en los comentarios del código como
b2
. La versión de búsqueda binaria del algoritmo es ahora más de dos veces más rápida que la simple.El segundo método comienza a ser más rápido para elegir más de cca 75 elementos en mi máquina (tenga en cuenta que la complejidad de cualquiera de los algoritmos no depende de la cantidad de elementos
MAX
).Vale la pena mencionar que los algoritmos anteriores generan los números aleatorios en orden ascendente. Pero sería sencillo agregar otra matriz en la que se guardarían los números en el orden en que se generaron y devolverla en su lugar (con un costo adicional insignificante
O(n)
). No es necesario mezclar la salida: sería mucho más lento.Tenga en cuenta que las fuentes están en C ++, no tengo Java en mi máquina, pero el concepto debería ser claro.
EDITAR :
Para divertirme, también he implementado el enfoque que genera una lista con todos los índices
0 .. MAX
, los elige al azar y los elimina de la lista para garantizar la singularidad. Como elegí bastante altoMAX
(5000), el rendimiento es catastrófico:// b1: 519515.000 msec // b2: 20312.000 msec std::vector<int> all_numbers(n_item_num); std::iota(all_numbers.begin(), all_numbers.end(), 0); // generate all the numbers for(size_t i = 0; i < n_number_num; ++ i) { assert(all_numbers.size() == n_item_num - i); int n = n_Rand(n_item_num - i - 1); // get a random number rand_num.push_back(all_numbers[n]); // put it in the output list all_numbers.erase(all_numbers.begin() + n); // erase it from the input } // generate random numbers
También implementé el enfoque con una
set
(una colección de C ++), que en realidad ocupa el segundo lugar en el punto de referenciab2
, siendo solo un 50% más lento que el enfoque con la búsqueda binaria. Eso es comprensible, ya queset
utiliza un árbol binario, donde el costo de inserción es similar al de la búsqueda binaria. La única diferencia es la posibilidad de obtener elementos duplicados, lo que ralentiza el progreso.// b1: 20250.000 msec // b2: 2296.000 msec std::set<int> numbers; while(numbers.size() < n_number_num) numbers.insert(n_Rand(n_item_num - 1)); // might have duplicates here // generate unique random numbers rand_num.resize(numbers.size()); std::copy(numbers.begin(), numbers.end(), rand_num.begin()); // copy the numbers from a set to a vector
El código fuente completo está aquí .
fuente
Puede usar una de las clases que implementan la interfaz Set ( API ), y luego, cada número que genere, use Set.add () para insertarlo.
Si el valor devuelto es falso, sabrá que el número ya se generó antes.
fuente
En lugar de hacer todo esto, cree un
LinkedHashSet
objeto y números aleatorios porMath.random()
función ... si ocurre alguna entrada duplicada, elLinkedHashSet
objeto no agregará ese número a su Lista ... Ya que en esta Clase de Colección no se permiten valores duplicados ... al final, obtienes una lista de números aleatorios que no tienen valores duplicados ....: Dfuente
Su problema parece reducirse a elegir k elementos al azar de una colección de n elementos. La respuesta de Collections.shuffle es, por lo tanto, correcta, pero como se señaló, ineficiente: es O (n).
Wikipedia: Fisher-Yates shuffle tiene una versión O (k) cuando la matriz ya existe. En su caso, no hay una matriz de elementos y crear la matriz de elementos podría ser muy costoso, digamos si el máximo fuera 10000000 en lugar de 20.
El algoritmo de reproducción aleatoria implica inicializar una matriz de tamaño n donde cada elemento es igual a su índice, seleccionando k números aleatorios de cada número en un rango con el máximo uno menos que el rango anterior, luego intercambiando elementos hacia el final de la matriz.
Puede hacer la misma operación en tiempo O (k) con un mapa de hash, aunque admito que es un poco molesto. Tenga en cuenta que esto solo vale la pena si k es mucho menor que n. (es decir, k ~ lg (n) más o menos), de lo contrario, debería utilizar la función aleatoria directamente.
Utilizará su mapa de hash como una representación eficiente de la matriz de respaldo en el algoritmo de reproducción aleatoria. Cualquier elemento de la matriz que sea igual a su índice no necesita aparecer en el mapa. Esto le permite representar una matriz de tamaño n en tiempo constante, no hay tiempo para inicializarla.
Elija k números aleatorios: el primero está en el rango de 0 a n-1, el segundo de 0 a n-2, el tercero de 0 a n-3 y así sucesivamente, a través de nk.
Trate sus números aleatorios como un conjunto de intercambios. El primer índice aleatorio cambia a la posición final. El segundo índice aleatorio cambia a la penúltima posición. Sin embargo, en lugar de trabajar contra una matriz de respaldo, trabaje contra su mapa de hash. Su mapa de hash almacenará todos los elementos que estén fuera de posición.
int getValue(i) { if (map.contains(i)) return map[i]; return i; } void setValue(i, val) { if (i == val) map.remove(i); else map[i] = val; } int[] chooseK(int n, int k) { for (int i = 0; i < k; i++) { int randomIndex = nextRandom(0, n - i); //(n - i is exclusive) int desiredIndex = n-i-1; int valAtRandom = getValue(randomIndex); int valAtDesired = getValue(desiredIndex); setValue(desiredIndex, valAtRandom); setValue(randomIndex, valAtDesired); } int[] output = new int[k]; for (int i = 0; i < k; i++) { output[i] = (getValue(n-i-1)); } return output; }
fuente
creating the array of elements could be very expensive
- ¿Por qué debería ser más caro crear una matriz que barajar? Creo que no hay absolutamente ninguna razón para el pesimismo en este punto :-)El siguiente código crea una secuencia de números aleatorios entre [1, m] que no se generó antes.
public class NewClass { public List<Integer> keys = new ArrayList<Integer>(); public int rand(int m) { int n = (int) (Math.random() * m + 1); if (!keys.contains(n)) { keys.add(n); return n; } else { return rand(m); } } public static void main(String[] args) { int m = 4; NewClass ne = new NewClass(); for (int i = 0; i < 4; i++) { System.out.println(ne.rand(m)); } System.out.println("list: " + ne.keys); } }
fuente
Hay un algoritmo de lote de tarjetas: usted crea una matriz ordenada de números (el "lote de tarjetas") y en cada iteración selecciona un número en una posición aleatoria (eliminando el número seleccionado del "lote de tarjetas", por supuesto).
fuente
Esta es una solución eficiente para la creación rápida de una matriz aleatoria. Después de la aleatorización, simplemente puede elegir el
n
-ésimo elementoe
de la matriz, incrementarn
y regresare
. Esta solución tiene O (1) para obtener un número aleatorio y O (n) para la inicialización, pero como compensación requiere una buena cantidad de memoria si n se vuelve lo suficientemente grande.fuente
Existe una solución más eficiente y menos engorrosa para números enteros que Collections.shuffle.
El problema es el mismo que elegir sucesivamente elementos de solo los elementos no seleccionados de un conjunto y ponerlos en orden en otro lugar. Esto es exactamente como repartir cartas al azar o sacar boletos de rifa ganadores de un sombrero o papelera.
Este algoritmo funciona para cargar cualquier arreglo y lograr un orden aleatorio al final de la carga. También funciona para agregar a una colección List (o cualquier otra colección indexada) y lograr una secuencia aleatoria en la colección al final de las adiciones.
Se puede hacer con una sola matriz, creada una vez, o con una colección ordenada numéricamente, como una Lista, en su lugar. Para una matriz, el tamaño de la matriz inicial debe ser el tamaño exacto para contener todos los valores previstos. Si no sabe cuántos valores pueden ocurrir de antemano, también funcionará el uso de una colección ordenada numéricamente, como ArrayList o List, donde el tamaño no es inmutable. Funcionará universalmente para una matriz de cualquier tamaño hasta Integer.MAX_VALUE, que es un poco más de 2,000,000,000. Los objetos de lista tendrán los mismos límites de índice. Su máquina puede quedarse sin memoria antes de que llegue a una matriz de ese tamaño. Puede ser más eficiente cargar una matriz con tipos de objeto y convertirla en alguna colección, después de cargar la matriz. Esto es especialmente cierto si la colección de destino no está indexada numéricamente.
Este algoritmo, exactamente como está escrito, creará una distribución muy uniforme donde no hay duplicados. Un aspecto MUY IMPORTANTE es que tiene que ser posible que la inserción del siguiente artículo se produzca hasta el tamaño actual + 1. Así, para el segundo artículo, podría ser posible almacenarlo en la ubicación 0 o la ubicación 1 Para el artículo 20, podría ser posible almacenarlo en cualquier ubicación, del 0 al 19. Es tan posible que el primer artículo permanezca en la ubicación 0 como que termine en cualquier otra ubicación. Es posible que el siguiente elemento nuevo vaya a cualquier parte, incluida la siguiente ubicación nueva.
La aleatoriedad de la secuencia será tan aleatoria como la aleatoriedad del generador de números aleatorios.
Este algoritmo también se puede utilizar para cargar tipos de referencia en ubicaciones aleatorias en una matriz. Dado que esto funciona con una matriz, también puede funcionar con colecciones. Eso significa que no tiene que crear la colección y luego mezclarla o ordenarla en el orden en que se inserten los objetos. La colección solo necesita tener la capacidad de insertar un elemento en cualquier lugar de la colección o adjuntarlo.
// RandomSequence.java import java.util.Random; public class RandomSequence { public static void main(String[] args) { // create an array of the size and type for which // you want a random sequence int[] randomSequence = new int[20]; Random randomNumbers = new Random(); for (int i = 0; i < randomSequence.length; i++ ) { if (i == 0) { // seed first entry in array with item 0 randomSequence[i] = 0; } else { // for all other items... // choose a random pointer to the segment of the // array already containing items int pointer = randomNumbers.nextInt(i + 1); randomSequence[i] = randomSequence[pointer]; randomSequence[pointer] = i; // note that if pointer & i are equal // the new value will just go into location i and possibly stay there // this is VERY IMPORTANT to ensure the sequence is really random // and not biased } // end if...else } // end for for (int number: randomSequence) { System.out.printf("%2d ", number); } // end for } // end main } // end class RandomSequence
fuente
Realmente todo depende exactamente para QUÉ necesitas la generación aleatoria, pero aquí está mi opinión.
Primero, cree un método independiente para generar el número aleatorio. Asegúrese de permitir límites.
public static int newRandom(int limit){ return generatedRandom.nextInt(limit); }
A continuación, querrá crear una estructura de decisión muy simple que compare valores. Esto se puede hacer de dos formas. Si tiene una cantidad muy limitada de números para verificar, una simple declaración IF será suficiente:
public static int testDuplicates(int int1, int int2, int int3, int int4, int int5){ boolean loopFlag = true; while(loopFlag == true){ if(int1 == int2 || int1 == int3 || int1 == int4 || int1 == int5 || int1 == 0){ int1 = newRandom(75); loopFlag = true; } else{ loopFlag = false; }} return int1; }
Lo anterior compara int1 con int2 a int5, además de asegurarse de que no haya ceros en los randoms.
Con estos dos métodos implementados, podemos hacer lo siguiente:
Seguido por:
Si tiene una lista más larga para verificar, entonces un método más complejo producirá mejores resultados tanto en la claridad del código como en los recursos de procesamiento.
Espero que esto ayude. Este sitio me ha ayudado tanto que me sentí en la obligación de al menos INTENTAR ayudar también.
fuente
Creé un fragmento que no genera ningún entero aleatorio duplicado. la ventaja de este fragmento es que puede asignarle la lista de una matriz y generar el elemento aleatorio también.
Clase de generador aleatorio sin duplicación
fuente
La forma más sencilla es utilizar nano DateTime como formato largo. System.nanoTime ();
fuente