Tengo un método que utiliza muestras aleatorias para aproximar un cálculo. Este método se llama millones de veces, por lo que es muy importante que el proceso de elección de los números aleatorios sea eficiente.Elección aleatoria de números
No estoy seguro de cuán rápido son las javas Random().nextInt
, pero mi programa no parece beneficiar tanto como me gustaría.
la hora de elegir los números al azar, hago lo siguiente (en semi pseudo-código):
// Repeat this 300000 times
Set set = new Set();
while(set.length != 5)
set.add(randomNumber(MIN,MAX));
Ahora, esto obviamente tiene un mal peor de los casos el tiempo de funcionamiento, ya que el azar-función en teoría puede agrega números duplicados por una eternidad, permaneciendo así en el ciclo while para siempre. Sin embargo, los números se eligen de {0..45}, por lo que un valor duplicado es poco probable.
Cuando uso el método anterior, es solo 40% más rápido que mi otro método, que no se aproxima, pero arroja el resultado correcto. Esto se ejecutó ~ 1 millón de veces, así que esperaba que este nuevo método fuera al menos un 50% más rápido.
¿Tiene alguna sugerencia para un método más rápido? O quizás conozcas una forma más eficiente de generar un conjunto de números aleatorios.
Para aclarar, aquí es los dos métodos:
// Run through all combinations (1 million). This takes 5 seconds
for(int c1 = 0; c1 < deck.length; c1++){
for(int c2 = c1+1; c2 < deck.length; c2++){
for(int c3 = c2+1; c3 < deck.length; c3++){
for(int c4 = c3+1; c4 < deck.length; c4++){
for(int c5 = c4+1; c5 < deck.length; c5++){
enumeration(hands, cards, deck, c1, c2, c3, c4, c5);
}
}
}
}
}
// Approximate (300000 combinations). This takes 3 seconds
Random rand = new Random();
HashSet<Integer> set = new HashSet<Integer>();
int[] numbers = new int[5];
while(enumerations < 300000){
set.clear();
while(set.size() != 5){
set.add(rand.nextInt(deck.length));
}
Iterator<Integer> i = set.iterator();
int n = 0;
while(i.hasNext()){
numbers[n] = i.next();
n++;
}
Después de algunas pruebas y elaboración de perfiles, he encontrado que este método es el más eficaz:
Random rand = new Random();
int[] numbers = new int[5];
ArrayList<Integer> list = new ArrayList<Integer>();
while(enumerations < 300000){
while(list.size() != 5) {
int i = rand.nextInt(deck.length);
if(!list.contains(i)) list.add(i);
}
int index = 0;
for(int i : list){ numbers[index] = i; index++; }
enumeration(hands, cards, deck,numbers);
}
¿Se puede repetir lo que sea que está tratando de lograr? ¿Estás tratando de generar un conjunto de N números distintos con cada llamada al método? Habla de comparar este método con otro "que no se aproxima" y el otro método es más rápido: ¿es el problema real la generación de números aleatorios o su método para hacer algún otro cálculo (aproximación vs no aproximación)? –
El problema es la generación de números aleatorios. Los otros cálculos no son relevantes, por lo que no los he mencionado en mi pregunta. –