98 votes

Génération de nombres aléatoires uniques en Java

J'essaie d'obtenir des nombres aléatoires compris entre 0 et 100. Mais je veux qu'ils soient uniques, et non répétés dans une séquence. Par exemple, si j'obtiens 5 numéros, ils doivent être 82,12,53,64,32 et non 82,12,53,12,32. J'ai utilisé ceci, mais cela génère les mêmes nombres dans une séquence.

Random rand = new Random();
selected = rand.nextInt(100);

5 votes

Vous pourriez créer un permutation aléatoire de la gamme 1..100 (il existe des algorithmes célèbres pour cela), mais arrêtez-vous après avoir déterminé le premier n éléments.

0 votes

0 votes

2voto

Ravindra babu Points 5571

Je suis venu ici à partir d'une autre question, qui a été dupliquée de cette question ( Génération d'un nombre aléatoire unique en java )

  1. Stockez de 1 à 100 numéros dans un tableau.

  2. Générer un nombre aléatoire entre 1 et 100 comme position et retourner le tableau [position-1] pour obtenir la valeur.

  3. Une fois que vous avez utilisé un nombre dans le tableau, marquez la valeur comme -1 (pas besoin de maintenir un autre tableau pour vérifier si ce nombre est déjà utilisé).

  4. Si la valeur dans le tableau est -1, récupérer le nombre aléatoire à nouveau pour récupérer le nouvel emplacement dans le tableau.

2voto

Devarsh Ranpara Points 21

J'ai une solution facile pour ce problème, Avec cela, nous pouvons facilement générer n nombre de numéros aléatoires uniques, C'est juste de la logique, tout le monde peut l'utiliser dans n'importe quelle langue.

for(int i=0;i<4;i++)
        {
            rn[i]= GenerateRandomNumber();
            for (int j=0;j<i;j++)
            {
                if (rn[i] == rn[j])
                {
                    i--;
                }
            }
        }

1voto

Kamran Hyder Points 11

Bien que ce soit un vieux fil de discussion, mais ajouter une autre option pourrait ne pas nuire. (Les fonctions lambda du JDK 1.8 semblent le rendre facile) ;

Le problème peut être décomposé en plusieurs étapes ;

  • Obtenir une valeur minimale pour la liste d'entiers fournie (pour laquelle générer des numéros aléatoires uniques).
  • Obtenez une valeur maximale pour la liste d'entiers fournie.
  • Utilisez la classe ThreadLocalRandom (du JDK 1.8) pour générer des valeurs entières aléatoires par rapport aux valeurs entières min et max trouvées précédemment, puis filtrez pour vous assurer que les valeurs sont bien contenues dans la liste fournie à l'origine. Enfin, appliquez distinct à l'intstream pour vous assurer que les nombres générés sont uniques.

Voici la fonction avec une description :

/**
 * 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;

}

Ainsi, pour obtenir 11 numéros aléatoires uniques pour l'objet de liste 'allIntegers', nous appellerons la fonction comme suit ;

    List<Integer> ids = getUniqueRandomInts(allIntegers,11);

La fonction déclare une nouvelle liste de tableaux 'generatedUniqueIds' et la remplit avec chaque entier aléatoire unique jusqu'au nombre requis avant de la retourner.

P.S. La classe ThreadLocalRandom évite une valeur de semence commune en cas de threads concurrents.

0voto

Rohit Anand Points 1

Essayez ceci

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);
    }
}

0voto

Jeffrey Chen Points 529

Choisissez n nombres aléatoires uniques de 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;
}

Imaginez une liste contenant des chiffres de 0 à m-1. Pour choisir le premier nombre, on utilise simplement rand.nextInt(m) . Puis on enlève le numéro de la liste. Maintenant, il reste m-1 nombres, donc nous appelons rand.nextInt(m-1) . Le nombre que nous obtenons représente la position dans la liste. S'il est inférieur au premier nombre, il s'agit du deuxième nombre, puisque la partie de la liste située avant le premier nombre n'a pas été modifiée par la suppression du premier nombre. Si la position est supérieure ou égale au premier nombre, le deuxième nombre est la position+1. En faisant quelques dérivations supplémentaires, on obtient cet algorithme.

Explication

Cet algorithme a une complexité O(n^2). Il est donc bon pour générer une petite quantité de numéros uniques à partir d'un grand ensemble. Alors que l'algorithme basé sur le brassage nécessite au moins O(m) pour effectuer le brassage.

De même, les algorithmes basés sur le shuffle ont besoin de mémoire pour stocker tous les résultats possibles pour effectuer le shuffle, ce dont cet algorithme n'a pas besoin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X