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

新手上路,请多包涵

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

原文由 AAaa 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

一种无需每次都重新生成随机数的可能解决方案是使用以下算法:

 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)

它在 startend (包括两者)之间生成一个随机数(int),并且不给你数组中包含的任何数字 exclude 所有其他数字以相同的概率出现。请注意,必须满足以下约束条件: exclude 升序排列,所有数字都在提供的范围内,并且所有数字都互不相同。

原文由 Howard 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

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

所以你得到一个范围长度,它与可能的有效数字的数量相同。换句话说:您已经移除了范围内的所有漏洞。

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

原文由 Fabian Barney 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题