简体   繁体   English

如何在Java中生成6个不同的随机数

[英]How to generate 6 different random numbers in java

I want to generate 6 different random numbers by using Math.random and store them into an array. 我想通过使用Math.random生成6个不同的随机数,并将它们存储到数组中。 How can I make sure that they are different? 我如何确保它们不同? I know I need to use for-loop to check the array but how... 我知道我需要使用for循环来检查数组,但是如何...

This is the range. 这是范围。 I only need numbers between 1 and 49. ( 1 + (int) (Math.random() * 49) ) 我只需要1到49之间的数字。(1 +(int)(Math.random()* 49))

In Java 8: 在Java 8中:

final int[] ints = new Random().ints(1, 50).distinct().limit(6).toArray();

In Java 7: 在Java 7中:

public static void main(final String[] args) throws Exception {
    final Random random = new Random();
    final Set<Integer> intSet = new HashSet<>();
    while (intSet.size() < 6) {
        intSet.add(random.nextInt(49) + 1);
    }
    final int[] ints = new int[intSet.size()];
    final Iterator<Integer> iter = intSet.iterator();
    for (int i = 0; iter.hasNext(); ++i) {
        ints[i] = iter.next();
    }
    System.out.println(Arrays.toString(ints));
}

Just a little messier. 只是有点混乱。 Not helped by the fact that it's pretty tedious to unbox the Set<Integer> into an int[] . Set<Integer>拆箱为int[]非常繁琐,这无济于事。

It should be noted that this solution should be fine of the number of required values is significantly smaller than the range. 应该注意的是,这种解决方案应该很好,其所需值的数量明显小于该范围。 As 1..49 is quite a lot larger than 6 you're fine. 因为1..496大很多,所以您可以。 Otherwise performance rapidly degrades. 否则性能会迅速下降。

Create a list containing the numbers 1 to 49. 创建一个包含数字1到49的列表。

Create a random number x between 0 and the size of the list, take the number being at index x in the list, and remove it from the list. 创建一个介于0和列表大小之间的随机数x ,使该数字位于列表中的索引x ,然后将其从列表中删除。

Repeat the previous step 5 times. 重复上一步5次。 And you're done. 这样就完成了。 Note that java.util.Random has a nextInt(int max) method that you should use instead of Math.random() . 请注意,您应该使用java.util.Random而不是Math.random()使用nextInt(int max)方法。

Note regarding performance: this solution has an advantage compared to the "try until you get 6 different numbers" various solutions: it runs in a O(n) time. 关于性能的注意事项:与“尝试直到获得6个不同的数字”各种解决方案相比,该解决方案具有一个优势:它运行时间为O(n)。 It doesn't matter much for 6 unique numbers out of 50, but if you want to get 48 or 49 unique random numbers out of 50, you'll start seeing a difference, because you might have to generate many random numbers before getting one that isn't already in the set. 50个中的6个唯一数无关紧要,但是如果要从50个中获得48个或49个唯一随机数,就会开始看到差异,因为您可能必须先生成许多随机数,然后才能获得一个尚未包含在集合中。

EDIT: 编辑:

to reduce the cost induced by the removal of the elements in the list, you could instead simply replace the element at index x with the last element of the list (and at the second iteration, with the element at size - 2, etc.) 为了减少由于删除列表中的元素而导致的成本,您可以简单地将索引x处的元素替换为列表中的最后一个元素(在第二次迭代中,将元素的大小更改为2,依此类推)。

Generate any 6 numbers (not necessarily different). 生成任意6个数字(不一定不同)。 Order them. 订购它们。

a1 <= a2 <= a3 <= a4 <= a5 <= a6 a1 <= a2 <= a3 <= a4 <= a5 <= a6

Now take these 6 numbers 现在取这6个数字

a1 < a2 + 1 < a3 + 2 < a4 + 3 < a5 + 4 < a6 + 5 a1 <a2 + 1 <a3 + 2 <a4 + 3 <a5 + 4 <a6 + 5

These 6 are different and random. 这6个是不同且随机的。

The idea of this construct comes from some combinatorial proofs. 这种构造的思想来自一些组合证明。

Its advantage is that it's simple, fast, and deterministic. 它的优点是简单,快速和确定性。
I think the time complexity is O(count*log(count)) . 我认为时间复杂度为O(count*log(count))
I wonder if it can be improved. 我想知道是否可以改进。

import java.util.TreeMap;

public class Test005 {

    public static void main(String[] args) {
        int count = 6;
        int min = 1;
        int max = 49;

        // random number mapped to the count of its occurrences
        TreeMap<Integer, Integer> mp = new TreeMap<Integer, Integer>();
        for (int i=0; i<count; i++){
             int d = ( min + (int) (Math.random() * (max-count+1)) );
             if (!mp.containsKey(d)){
                 mp.put(d, 0);
             }
             mp.put(d, mp.get(d) + 1);
        }

        // now ensure the output numbers are different
        int j = 0;
        for (int num : mp.keySet()){
            int cnt = mp.get(num);
            for (int i=0; i<cnt; i++){
                System.out.println(num + j);
                j++;
            }
        }
    }

}

You can use a Set . 您可以使用Set

Set<Integer> s = new HashSet<>();
while(s.size() != 6){
   s.add(1 + (int) (Math.random() * 49));
}

Integer[] arr = s.toArray(new Integer[s.size()]);

This is enough to do this in your case because the number of distinct random numbers is relatively small compared to the size of the range you generate them. 就您的情况而言,这样做就足够了,因为与您生成随机数范围的大小相比,不同随机数的数量相对较小。

Otherwise I would go with @JBNizet approach. 否则,我会使用@JBNizet方法。

I've just came up with a small idea for Java 8-. 我刚刚想到了一个Java 8的小主意。

Set<Integer> set = new LinkedHashSet<>();
while(set.size() != 6)
    set.add(rnd.nextInt(49) + 1);

Instead of checking that the array has no duplicates, you can use a bit more smartness while generating the numbers, such that uniqueness is enforced at the outset. 您可以在生成数字时使用更多的智能功能,而不是检查数组是否没有重复项,这样一开始就强制要求唯一性。

  1. Create a boolean[] as long as your range (49 entries); 创建一个boolean[] ,只要您的范围(49个条目);
  2. generate a random number from the full range; 从整个范围生成一个随机数;
  3. put that number into your output array; 将该数字放入输出数组中;
  4. "cross out" the corresponding index in the boolean[] ; “划掉” boolean[]的相应索引;
  5. now generate another random number, but curtail the range by one (now 48); 现在生成另一个随机数,但将范围缩小一个(现在为48);
  6. instead of directly using that number as output, scan your boolean[] , counting all the non-crossed entries. 而不是直接使用该数字作为输出,而是扫描boolean[] ,计算所有非交叉条目。 Stop when you reach the count equal to the random number generated in step 5. The number corresponding to that entry is your output number; 当您达到等于在步骤5中生成的随机数的计数时,请停止。
  7. go to step 4. 转到步骤4。

in your case n=6 在您的情况下,n = 6

     public static int[] chooseAny(int n){
        int[] lottery = new int[n];
        int[] chooseFrom = new int[49];
        for(int i=1 ; i <= 49 ; i++)
            chooseFrom[i-1] = i;
        Random rand = new Random();
        int N = 49;
        int index;
        for(int i=0 ; i < n ; i++){
            //pick random index
            index = rand.nextInt(N);
            lottery[i] = chooseFrom[index];
            chooseFrom[index] = chooseFrom[N-1];
            N--;
        }
        return lottery;
    }

Just keep generating numbers and adding them to the array as long as they are unique; 只要保持生成数字并将它们添加到数组中即可,只要它们是唯一的即可。 psuedocode: 伪代码:

num = genNextRand()

For (array length)
    If (num not in array)
        addToArray()

Repeat while length not equal 6

Create a variable last ; 最后创建一个变量; initialize it to 0 . 将其初始化为0

Next, in a loop x from 0 to 5, create a random number between last +1 and 49-6+ x . 接下来,在从0到5的循环x中 ,在last +149-6+ x之间创建一个随机数。 Store this number in a list, and set last to the number generated this way. 将此数字存储在列表中, last设置为以此方式生成的数字。

You will end up with an ordered list of 6 random numbers in the range of 1..49 with no repeats. 您将最终得到1个随机数的有序列表,范围是1..49,没有重复。

That code generate numbers from 6 to 0 and save in ArrayList. 该代码生成从6到0的数字并将其保存在ArrayList中。

If generated number was duplicated the program generate numbers again. 如果生成的号码重复,程序将再次生成号码。

If generated number is different that number is added. 如果生成的数字不同,则会添加该数字。

Code: 码:

private ArrayList<Integer> arraylist = new ArrayList<Integer>();

private Random rand = new Random();

public void insertNumber() {
    while (true) {
        int i = generateNumber();
        if(!isGenerateNumberExists(i)){
            addNumber(i);
            break;
        }
    }
}
//Generate numbers
private int generateNumber() {
    return rand.nextInt(6);
}
//Confirm if that number exists
private boolean isGenerateNumberExists(int y) {
    for (int num : arraylist) {
        if (num == y) {
            return true;
        }
    }
    return false;
}
//Add number to arrayList
private void addNumber(int x) {
    arraylist.add(x);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM