如何在一个范围内生成随机数,但排除一些随机数?

2022-09-01 03:39:04

如何在一个范围内生成一个随机数,但排除一些随机数,而不继续生成并检查生成的数字是否是我要排除的数字之一?


答案 1

每次不随机再生的一种可能的解决方案是使用以下算法:

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

此方法可以使用数组引用来调用,例如

int[] ex = { 2, 5, 6 };
val = getRandomWithExclusion(rnd, 1, 10, ex)

或直接在呼叫中插入号码:

val = getRandomWithExclusion(rnd, 1, 10, 2, 5, 6)

它在 和 (两者兼而有)之间生成一个随机数 (int),并且不会为您提供数组中包含的任何数字。所有其他数字以相等的概率出现。请注意,以下约束必须成立:按升序排序,所有数字都在提供的范围内,并且所有数字都是相互不同的。startendexcludeexclude


答案 2
/**
 * @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;
}

这个想法是将其中随机数产生的范围减小到该范围内被排除的数字的开始和结束之间的差值减去计数。

因此,您将获得一个与可能的有效数字计数相同的范围长度。换句话说:您已经从范围内移除了所有孔洞。

生成随机数后,您必须将“孔”放回范围内。这可以通过递增生成的数字来实现,只要排除的数字小于或等于生成的数字即可。较低的排除数字是生成数字之前范围内的“孔”。生成的数字会向右移动,用于该数字之前的每个孔。


推荐