JAVA中如何产生20个不同的随机数?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA中如何产生20个不同的随机数?相关的知识,希望对你有一定的参考价值。
上图是产生随机数的方法,检验无误,但如何能让每个随机数都不同呢?
如果学过集合的话,把随机数保存到Set集合里,当Size等于20的时候,就满足了。没过学集合的话,每生成一个随机数,就遍历一下数组元素,如果已存在这个数,就重新生成一个。 参考技术A 随机数种子是固定的,所以你可以通过使用计算机当前的时间使得随机数每次执行得结果不同 参考技术B 你判断下如果和数组里的数相同就不放进数组不就妥了
或者用set
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class TestObject
/**
* @param args
*/
public static void main(String[] args)
// TODO Auto-generated method stub
int i,setLength = 0;
// int a[] = new int[20];
Random random = new Random();
Set<Integer> set =new HashSet<Integer>();
while(setLength < 20)
int temp = random.nextInt(100);
set.add(temp);
setLength = set.size();
for(int a:set)
System.out.println(a);
参考技术C 这个代码不对啊,随机数出现重复,数组中不就出现重复元素了么 参考技术D 任务,走人
如何在java中生成6个不同的随机数
【中文标题】如何在java中生成6个不同的随机数【英文标题】:How to generate 6 different random numbers in java 【发布时间】:2014-04-30 07:47:32 【问题描述】:我想使用 Math.random 生成 6 个不同的随机数并将它们存储到一个数组中。 我怎样才能确保它们是不同的?我知道我需要使用 for 循环来检查数组,但是如何...
这是范围。我只需要 1 到 49 之间的数字。 ( 1 + (int) (Math.random() * 49) )
【问题讨论】:
只要它们是唯一的,就继续生成数字并将它们添加到数组中;生成一个数字并与数组中的其他数字进行对比。 与手工操作完全一样。掷骰子得到一个数字,检查它是否是你还没有的数字,记录它,重复直到你有你需要的数字。 -- 或者实现自己的shuffle,这是更通用的解决方案。 【参考方案1】:生成任意 6 个数字(不一定不同)。订购它们。
a1
现在取这 6 个数字
a1
这 6 个是不同且随机的。
这个结构的想法来自一些组合证明。
它的优点是简单、快速且具有确定性。
我认为时间复杂度是O(count*log(count))
。
我想知道它是否可以改进。
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++;
【讨论】:
我喜欢这个主意。但是您似乎忘记处理增加的数字超出范围的情况 是的,看来我应该做int max = 44;
然后增加的不能超过49。
这不会降低获得0到5范围内数字的概率吗?它仍然是一个很好的可扩展解决方案,比其他解决方案更快【参考方案2】:
在 Java 8 中:
final int[] ints = new Random().ints(1, 50).distinct().limit(6).toArray();
在 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));
只是有点混乱。将Set<Integer>
拆箱成int[]
非常乏味这一事实无济于事。
需要注意的是,这个解决方案应该很好,所需值的数量明显小于范围。因为1..49
比6
大很多,所以你很好。否则性能会迅速下降。
【讨论】:
OP 的要求无关紧要,但仍然......我不禁不欣赏这种性能不佳的可爱单线。我在 Clojure 中看到了我的分享。 我同意@MarkoTopolnik。虽然这是一个不错的单行,但 JBNizet 的解决方案要高效得多。 +1 虽然。 在这两种情况下都使用 HashSet,这是一个糟糕的选择。例如以任何顺序将 0 到 10 添加到 HashSet 中,它们会按排序顺序排列。即 HashSet 不是那么随机。 @PeterLawrey 我没有考虑过Set
中的项目的自然顺序——这是一个很好的观点。我想LinkedHashSet
会在第二种情况下工作。在第一种情况下,我不确定如何解决...【参考方案3】:
您可以使用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()]);
这足以在您的情况下执行此操作,因为与您生成它们的范围大小相比,不同随机数的数量相对较小。
否则我会使用@JBNizet 方法。
【讨论】:
【参考方案4】:创建一个包含数字 1 到 49 的列表。
创建一个介于 0 和列表大小之间的随机数 x
,取列表中索引 x
处的数字,并将其从列表中删除。
重复上一步 5 次。你完成了。请注意,java.util.Random
有一个 nextInt(int max)
方法,您应该使用它来代替 Math.random()
。
关于性能的注意事项:与“尝试直到获得 6 个不同的数字”各种解决方案相比,此解决方案具有优势:它在 O(n) 时间内运行。 50 个中的 6 个唯一数字无关紧要,但是如果您想从 50 个中获得 48 或 49 个唯一随机数,您将开始看到差异,因为您可能必须先生成许多随机数才能获得一个不在集合中。
编辑:
为了减少删除列表中的元素所带来的成本,您可以简单地将索引x
处的元素替换为列表的最后一个元素(在第二次迭代中,使用大小为 - 2等)
【讨论】:
只需 替换 使用末尾的数字就足够了,除非您使用数组的末尾作为输出。不过,您可以使用subList
轻松做到这一点。
这不会改变选中号码的分布吗?至少对于那个被替换的号码,被选中的几率是其他号码的两倍。此外,对于替换为 size-2 等,您需要检查您当前选择的数字是否不在 index = size (或 size-2...)。【参考方案5】:
只要它们是唯一的,就继续生成数字并将它们添加到数组中;伪代码:
num = genNextRand()
For (array length)
If (num not in array)
addToArray()
Repeat while length not equal 6
【讨论】:
【参考方案6】:您可以在生成数字时使用更多的智能,而不是检查数组是否有重复项,这样一开始就强制执行唯一性。
-
创建一个
boolean[]
,只要您的范围(49 个条目);
从全范围生成一个随机数;
将该数字放入您的输出数组中;
“划掉”boolean[]
中对应的索引;
现在生成另一个随机数,但将范围缩小一(现在为 48);
不要直接使用该数字作为输出,而是扫描您的boolean[]
,计算所有未交叉的条目。当您达到等于步骤 5 中生成的随机数的计数时停止。与该条目对应的数字就是您的输出数;
转到第 4 步。
【讨论】:
我不明白(阅读 2-3 次)。我想知道这是否与我的回答中建议的方法有关。你能发布一些关于这个算法的描述的链接吗? 也许是这个? ***.com/questions/196017/unique-random-numbers-in-o1 @peter.petrov:这与我的回答基本相同,只是不是从列表中删除数字,而是在布尔数组中将它们标记为已删除,并且不计算逻辑删除的数字迭代时。现在回想起来,我不确定它是否会比我的算法更有效,只要从列表中删除数字,它就会变得越来越高效。 哦...好吧,不完全相信,但好吧,我相信你这个;) @peter.petrov:交换数字而不是删除它们确实是个好主意。我不叫 Knuth 也不叫 Fisher-Yates 是有充分理由的 :-)【参考方案7】:创建一个变量last;将其初始化为0
。
接下来,在从 0 到 5 的循环 x 中,创建一个介于 <em>last</em>+1
和 49-6+<em>x</em>
之间的随机数。将此号码存储在列表中,并将<em>last</em>
设置为以这种方式生成的号码。
您最终会得到一个 1..49 范围内的 6 个随机数的有序列表,没有重复。
【讨论】:
【参考方案8】:在你的情况下 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;
【讨论】:
【参考方案9】:我刚刚想出了一个关于 Java 8 的小想法。
Set<Integer> set = new LinkedHashSet<>();
while(set.size() != 6)
set.add(rnd.nextInt(49) + 1);
【讨论】:
【参考方案10】:该代码生成从 6 到 0 的数字并保存在 ArrayList 中。
如果生成的号码重复,程序会再次生成号码。
如果生成的数字不同,则添加该数字。
代码:
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);
【讨论】:
欢迎来到 SO!尽管这可能会回答问题,但请尝试添加有关如何以及为什么这是合适答案的信息。此外,添加链接以支持您的声明将增加权重!以上是关于JAVA中如何产生20个不同的随机数?的主要内容,如果未能解决你的问题,请参考以下文章