web-dev-qa-db-fra.com

Générer des 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'ai 5 nombres, ils devraient être 82,12,53,64,32 et non 82,12,53,12,32 Je l'ai utilisé, mais cela génère les mêmes numéros dans une séquence.

Random Rand = new Random();
selected = Rand.nextInt(100);
65
Ömer Faruk AK
  • Ajoutez chaque numéro de la plage de manière séquentielle dans une structure list .
  • Shuffle il.
  • Prenez le premier 'n'.

Voici une implémentation simple. Ceci imprimera 3 nombres aléatoires uniques dans la plage 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));
        }
    }
}

Comme Mark Byers l’a souligné dans une réponse supprimée, la première partie du correctif avec l’approche originale consiste à n’utiliser qu’une seule instance Random

C'est ce qui fait que les chiffres sont identiques. Une instance Random est générée par l'heure actuelle en millisecondes. Pour une valeur graine particulière, l'instance 'random' renverra exactement la même séquence de pseudo aléatoire nombres.

109
Andrew Thompson

Avec Java 8+, vous pouvez utiliser la méthode ints de Random pour obtenir un IntStream de valeurs aléatoires, puis distinct et limit pour réduire le flux à un certain nombre de valeurs aléatoires uniques. .

ThreadLocalRandom.current().ints(0, 100).distinct().limit(5).forEach(System.out::println);

Random a aussi des méthodes qui créent LongStreams et DoubleStreams si vous en avez besoin.

Si vous souhaitez que tous (ou une grande quantité) des nombres d'une plage soient dans un ordre aléatoire, il serait peut-être plus efficace d'ajouter tous les nombres à une liste, de la mélanger et de prendre le premier n, car l'exemple ci-dessus est actuellement implémenté. en générant des nombres aléatoires dans la plage demandée et en les passant dans un ensemble (de la même manière que réponse de Rob Kielty ), ce qui peut nécessiter de générer beaucoup plus que le montant passé à limiter, car la probabilité de générer un nouveau nombre unique diminue avec chacun trouvé. Voici un exemple de l'inverse:

List<Integer> range = IntStream.range(0, 100).boxed()
        .collect(Collectors.toCollection(ArrayList::new));
Collections.shuffle(range);
range.subList(0, 99).forEach(System.out::println);
39
Alex
  1. Créez un tableau de 100 nombres, puis randomisez leur ordre.
  2. Concevez un générateur de nombres pseudo-aléatoires avec une plage de 100.
  3. Créez un tableau booléen de 100 éléments, puis définissez un élément sur true lorsque vous choisissez ce nombre. Lorsque vous choisissez le numéro suivant, vérifiez le tableau et réessayez si l'élément de tableau est défini. (Vous pouvez créer un tableau booléen facile à effacer avec un tableau de long dans lequel vous déplacez et masquez pour accéder à des bits individuels.)
17
Hot Licks

Utilisez Collections.shuffle() sur les 100 numéros et sélectionnez les cinq premiers, comme indiqué ici .

15
trashgod

Je pense que cette méthode mérite d'être mentionnée.

   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;
    }
10
Kenny Cason

J'ai refabriqué la réponse d'Anand pour utiliser non seulement les propriétés uniques d'un ensemble, mais aussi utiliser le booléen false renvoyé par le set.add() lorsqu'un ajout à l'ensemble échoue.

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

J'ai fait ça comme ça.

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

Cela fonctionnera pour générer des nombres aléatoires uniques ................

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

Je viens ici d'une autre question, qui a été dupliquée de cette question ( Générer un nombre aléatoire unique en Java )

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

  2. Générer un nombre aléatoire compris entre 1 et 100 en tant que position et renvoyer un tableau [position-1] pour obtenir la valeur 

  3. Une fois que vous avez utilisé un nombre dans un tableau, indiquez -1 (inutile de conserver un autre tableau pour vérifier si ce nombre est déjà utilisé)

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

2
Ravindra babu

Une méthode intelligente consiste à utiliser les exposants d’un élément primitif dans le module.

Par exemple, 2 est une racine primitive mod 101, ce qui signifie que les puissances de 2 mod 101 vous donnent une séquence non répétitive qui voit chaque nombre de 1 à 100 inclus:

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

En code Java, vous écririez:

void randInts() {
int num=1;
for (int ii=0; ii<101; ii++) {
    System.out.println(num);
    num= (num*2) % 101;
    }
}

Trouver une racine primitive pour un module spécifique peut être délicat, mais la fonction "primroot" de Maple le fera pour vous.

1
A T - student

Ce n'est pas très différent des autres réponses, mais je voulais le tableau d'entiers à la fin:

    Integer[] indices = new Integer[n];
    Arrays.setAll(indices, i -> i);
    Collections.shuffle(Arrays.asList(indices));
    return Arrays.stream(indices).mapToInt(Integer::intValue).toArray();
0
AbuNassar

J'ai une solution facile à ce problème, Avec cela, nous pouvons facilement générer un nombre n de nombres aléatoires uniques, Sa logique est que n'importe qui 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--;
                }
            }
        }
0
Devarsh Ranpara

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);
    }
}
0
Rohit Anand

vous pouvez utiliser un tableau booléen pour renseigner la valeur true si la valeur est prise, sinon, naviguez dans un tableau booléen pour obtenir la valeur indiquée ci-dessous 

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

    }

}
0
Sachin Rane

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 nombres de 0 à m-1. Pour choisir le premier numéro, nous utilisons simplement Rand.nextInt(m). Supprimez ensuite le numéro de la liste. Maintenant, il reste m-1 nombres, nous appelons donc Rand.nextInt(m-1). Le nombre que nous obtenons représente la position dans la liste. S'il est inférieur au premier numéro, il s'agit du deuxième numéro, car la partie de la liste précédant le premier numéro n'a pas été modifiée par la suppression du premier numéro. Si la position est supérieure ou égale au premier nombre, le deuxième nombre est la position + 1. Faites un peu plus de dérivation, vous pouvez obtenir cet algorithme.

Explication

Cet algorithme a une complexité de O (n ^ 2). Il est donc utile de générer une petite quantité de nombres uniques à partir d’un grand ensemble. Bien que l'algorithme basé sur la lecture aléatoire ait besoin d'au moins O(m) pour faire la lecture aléatoire.

De plus, l’algorithme basé sur la lecture aléatoire a besoin de mémoire pour stocker tous les résultats possibles, ce qui n’a pas besoin de cet algorithme.

0
Jeffrey Chen

Vous trouverez ci-dessous une méthode pour générer un nombre unique toujours. La fonction aléatoire génère un nombre et le stocke dans un fichier texte, puis la prochaine fois qu’elle le vérifie dans un fichier, le compare et génère un nouveau numéro unique, ce qui permet de créer un nouveau numéro unique.

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;

}
0
user4182613