在Java中生成唯一的随机数

问题描述 投票:67回答:17

我试图获得0到100之间的随机数。但是我希望它们是唯一的,而不是在序列中重复。例如,如果我得到5个数字,它们应该是82,12,53,64,32而不是82,12,53,12,32我使用它,但它在序列中生成相同的数字。

Random rand = new Random();
selected = rand.nextInt(100);
java random
17个回答
121
投票
  • list结构中按顺序添加范围中的每个数字。
  • Shuffle它。
  • 拿第一个'n'。

这是一个简单的实现。这将打印1-10范围内的3个唯一随机数。

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

正如Mark Byers在现在删除的答案中指出的那样,原始方法的修复的第一部分是仅使用单个Random实例。

这就是导致数字相同的原因。 Random实例以当前时间(以毫秒为单位)播种。对于特定的种子值,“随机”实例将返回完全相同的伪随机数序列。


2
投票

我是从另一个问题来到这里的,这个问题已经复制了(Generating unique random number in java

  1. 在数组中存储1到100个数字。
  2. 生成1到100之间的随机数作为位置并返回数组[position-1]以获取值
  3. 在数组中使用数字后,将值标记为-1(无需维护另一个数组以检查是否已使用此数字)
  4. 如果数组中的值为-1,则再次获取随机数以获取数组中的新位置。

0
投票

试试这个

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
投票

这与其他答案没有显着差异,但我最终想要整数数组:

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

0
投票

以下是我用来始终生成唯一编号的方法。随机函数生成数字并将其存储在文本文件中,然后下次在文件中检查它时比较它并生成新的唯一编号,因此这样总会有一个新的唯一编号。

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
投票

您可以使用布尔数组来填充true,如果采用其他值,则通过布尔数组导航以获取值,如下所示

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
投票

我有这个问题的简单解决方案,有了这个我们可以很容易地生成n个独特的随机数,它只是逻辑,任何人都可以在任何语言中使用它。

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

0
投票

选择从0到m-1的n个唯一随机数。

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

想象一下包含从0到m-1的数字的列表。要选择第一个数字,我们只需使用rand.nextInt(m)。然后从列表中删除该号码。现在还有m-1个数字,所以我们称之为rand.nextInt(m-1)。我们得到的数字代表了列表中的位置。如果它小于第一个数字,则它是第二个数字,因为第一个数字之前的列表部分没有通过删除第一个数字而改变。如果位置大于或等于第一个数字,则第二个数字是位置+ 1。做一些进一步的推导,你可以得到这个算法。

说明

该算法具有O(n ^ 2)复杂度。因此,从大型集合中生成少量唯一数字是有益的。虽然基于混合的算法需要至少O(m)来进行混洗。

另外基于shuffle的算法需要内存来存储每个可能的结果来进行shuffle,这个算法不需要。


-2
投票

检查一下

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

43
投票

使用Java 8+,您可以使用intsRandom方法获得随机值的IntStream,然后使用distinctlimit将流减少为许多唯一的随机值。

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

如果你需要那些,Random也有创造LongStreams和DoubleStreams的方法。

如果您希望以随机顺序在一个范围内的所有(或大量)数字,将所有数字添加到列表中更有效,将其洗牌并取第一个n,因为上面的示例当前已实现通过在所请求的范围内生成随机数并将它们传递给集合(类似于Rob Kielty's answer),这可能需要生成比传递到限制的数量多得多的数量,因为生成新唯一数字的概率随着每个发现的数量而减少。以下是另一种方式的示例:

List<Integer> range = IntStream.range(0, 100).boxed()
        .collect(Collectors.toCollection(ArrayList::new));
Collections.shuffle(range);
range.subList(0, 99).forEach(System.out::println);

18
投票
  1. 创建一个包含100个数字的数组,然后随机化它们的顺序。
  2. 设计范围为100的伪随机数生成器。
  3. 创建一个包含100个元素的布尔数组,然后在选择该数字时将元素设置为true。当您对数组选择下一个数字检查时,如果设置了数组元素,请再次尝试。 (您可以创建一个易于清除的布尔数组,其中包含long数组,您可以在其中移动并屏蔽以访问各个位。)

16
投票

在所有100个数字上使用Collections.shuffle()并选择前五个,如图所示here


11
投票

我觉得这种方法值得一提。

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

8
投票

我重新考虑了Anand的答案,不仅要使用Set的唯一属性,还要使用set.add()返回的布尔值false,当添加到集合失败时。

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

6
投票

我这样做了。

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

4
投票

这将产生独特的随机数................

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
投票

一种聪明的方法是在模数中使用原始元素的指数。

例如,2是原始根mod 101,意味着2 mod 101的幂给出了一个非重复序列,它可以看到从1到100的每个数字:

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

在Java代码中,您可以编写:

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

查找特定模数的原始根可能很棘手,但Maple的“primroot”函数将为您完成此操作。

© www.soinside.com 2019 - 2024. All rights reserved.