Java 如何在一个范围内生成一个随机数但排除一些?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6443176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I generate a random number within a range but exclude some?
提问by AAaa
How can I generate a random number within a range but exclude some, without keep generating and checking if the generated number is one of those that I want to exclude?
如何在一个范围内生成一个随机数但排除一些,而不继续生成并检查生成的数字是否是我想要排除的数字之一?
采纳答案by Howard
One possible solution without regeneration the random each time is to use the following algorithm:
每次不重新生成随机数的一种可能解决方案是使用以下算法:
public int getRandomWithExclusion(Random rnd, int start, int end, int... exclude) {
int random = start + rnd.nextInt(end - start + 1 - exclude.length);
for (int ex : exclude) {
if (random < ex) {
break;
}
random++;
}
return random;
}
This method can be either called with an array reference, e.g.
可以使用数组引用调用此方法,例如
int[] ex = { 2, 5, 6 };
val = getRandomWithExclusion(rnd, 1, 10, ex)
or by directly inserting the numbers into the call:
或直接将号码插入通话中:
val = getRandomWithExclusion(rnd, 1, 10, 2, 5, 6)
It generates a random number (int) between start
and end
(both inclusive) and does not give you any number which is contained in the array exclude
. All other numbers occur with equal probability. Note, that the following constrains must hold: exclude
is sorted ascendingly and all numbers are within the range provided and all of them are mutually different.
它在start
和之间生成一个随机数 (int) end
(两者都包括在内),并且不会为您提供包含在数组中的任何数字exclude
。所有其他数字都以相同的概率出现。请注意,以下约束必须成立:exclude
升序排序,所有数字都在提供的范围内,并且它们都互不相同。
回答by Ax.
Create a map that takes the output of a random function without the range restriction and map it to the range you want with restrictions.
创建一个地图,该地图获取没有范围限制的随机函数的输出,并将其映射到您想要的有限制范围的范围。
For example, if I want a random int from 1-10 but never 7 I could do something like this:
例如,如果我想要一个 1-10 的随机整数,但永远不会是 7,我可以这样做:
int i = rand(1, 9);
if i>=7
i++;
return i;
As long as you ensure that your mapping is 1:1, you can avoid skewing the randomness of your rand
function.
只要确保映射为 1:1,就可以避免rand
函数的随机性发生偏差。
回答by LainIwakura
Depending on how large the list of random numbers you're excluding, I would just generate your numbers and check if it's in the array of excluded numbers- if it is, just discard it. I know you don't want to check every time, but I can't think of another way besides specifying the ranges explicitly and if you have more than 5 numbers you're excluding that might be a bit worse.
根据您排除的随机数列表的大小,我只会生成您的数字并检查它是否在排除的数字数组中 - 如果是,则丢弃它。我知道您不想每次都检查,但除了明确指定范围之外,我想不出另一种方法,如果您有 5 个以上的数字,您要排除它可能会更糟。
回答by Snicolas
Something that could work and applies both to int and double numbers could be like :
可以工作并适用于 int 和 double 数字的东西可能是这样的:
public int getRandomNumberWithExclusion( int start, int end )
{
Random r = new Random();
int result = -1;
do
{
result = start + r.nextInt( end - start );
}//do
while( !isAllowed( result ) );
return result;
}//met
private boolean isAllowed( int number )
{
//your test for restricted values here
}//met
Regards, Stéphane
问候, 斯蒂芬
回答by anizzomc
The best aproach that you can follow to randomize numbers, excluding some is selecting the numbers that you want first and then randomly select the numbers selected. For example, in pseudocode:
您可以遵循的对数字进行随机化的最佳方法(排除某些方法)是先选择您想要的数字,然后随机选择所选的数字。例如,在伪代码中:
List<Number> numbers;
numbers.add(1);
numbers.add(2);
numbers.add(3);
//You can do a "for" without adding the excluded numbers..
//Then, your randomizer could be...
public Number getRandoNumber() {
int index = Random.get(0, numbers.size());
return numbers.get(index);
}
Now, you don't need to check if the "generated number" is allowed or not, because it doesn't exist at all.
现在,您不需要检查“生成的数字”是否被允许,因为它根本不存在。
If you don′t want them to repeat, you can do something like:
如果您不想让它们重复,您可以执行以下操作:
Collections.shuffle(numbers);
public Number getRandomNotRepeat() {
if(numbers.size() == 0)
throw new RuntimeException("No more numbers");
Number n = numbers.get(0);
numbers.removeFirst();
return n;
}
This is all pseudo code, don′t copy and paste!
以上均为伪代码,请勿复制粘贴!
回答by Fabian Barney
/**
* @param start start of range (inclusive)
* @param end end of range (exclusive)
* @param excludes numbers to exclude (= numbers you do not want)
* @return the random number within start-end but not one of excludes
*/
public static int nextIntInRangeButExclude(int start, int end, int... excludes){
int rangeLength = end - start - excludes.length;
int randomInt = RANDOM.nextInt(rangeLength) + start;
for(int i = 0; i < excludes.length; i++) {
if(excludes[i] > randomInt) {
return randomInt;
}
randomInt++;
}
return randomInt;
}
The idea is to reduce the range wherein the random number is generated to the difference between start and end minus count of numbers within that range that are excluded.
这个想法是将生成随机数的范围减少到开始和结束之间的差减去该范围内被排除的数字的数量。
So you get a range length which is identical with the count of possible valid numbers. In other words: You've removed all holes from range.
所以你得到的范围长度与可能的有效数字的数量相同。换句话说:您已经从范围内删除了所有漏洞。
After generating the random number you've to put the "holes" back in the range. This can be achieved by incrementing the generated number as long as there are excluded numbers lower than or equal to the generated one. The lower exclude numbers are "holes" in the range before the generated number. And the generated number is shifted to right for every hole before that number.
生成随机数后,您必须将“洞”放回范围内。只要排除的数字小于或等于生成的数字,就可以通过增加生成的数字来实现这一点。较低的排除数字是生成数字之前范围内的“空洞”。并且对于该数字之前的每个孔,生成的数字都会向右移动。
回答by rochal
I think the additional question is: What are the numbers you want to exlcude? Do they represent some sort of rangeor are they totally random?
我认为附加的问题是:您要排除的数字是多少?它们代表某种范围还是完全随机?
If it was a range of numbers you want to ignore, you could generate your random numbers from within few sets that represent only valid numbers:
如果这是您想要忽略的一系列数字,您可以从仅代表有效数字的几组中生成随机数:
rand(1,9);
rand(15,19);
rand(22,26);
this way you are sure you will never select excluded: <0,10,11,12,13,14,20,21,>27
这样你就可以确定你永远不会选择排除:<0,10,11,12,13,14,20,21,>27
Then, when you get your 3 numbers, you could again randomly select one of them.
然后,当您获得 3 个号码时,您可以再次随机选择其中一个。
If excluded numbers are all over the place than I'm afraid you'd have to check it every time against some sort of collection of excluded numbers.
如果排除的数字到处都是,那么恐怕您每次都必须根据某种排除的数字集合来检查它。
回答by Nishi Sahlot
exclude numbers should be with in range parameter
排除数字应该在范围内参数
private int GiveMeANumber(int range,int... exclude)
{
Set<Integer> integers=new HashSet<>();
int count=range;
for(int i=0;i<count;i++)
integers.add(i);
integers.removeAll(Arrays.asList(exclude));
int index = new Random().nextInt(range - exclude.length);
count=0;
for (int value:integers){
if(count==index)
return value;
count++;
}
return 0;
}