1. 概述

本文,我们将介绍几种不同的随机数生成方法,在给定范围内。

2. 在给定范围内生成随机数

2.1. 使用 Math.random()

我们知道 Math.random() 会返回一个大于等于 0.0 且小于 1.0 的 double 类型的随机值。

下面使用 Math.random() 方法在给定范围内生成随机数,取值区间([min, max)):

public int getRandomNumber(int min, int max) {
    return (int) ((Math.random() * (max - min)) + min);
}

Math.random() 返回 0.0 时,这是能取到的最小值:

0.0 * (max - min) + min => min

因此,我们能得到的最低数字就是 min

由于 1.0 是 Math.random() 的上限(不含):

1.0 * (max - min) + min => max - min + min => max

所以,我们方法返回的上限是 max(不含)。

2.2. 使用 Random.nextInt()

同样,我们也可以使用 java.util.Random.nextInt() 方法获取随机数:

public int getRandomNumberUsingNextInt(int min, int max) {
    Random random = new Random();
    return random.nextInt(max - min) + min;
}

最小值min(含),上限 max(不含)。

2.3. 使用 Random.ints()

方法三,java.util.Random.ints() 方法返回一个随机整数的 IntStream

因此,我们可以利用 java.util.Random.ints() 方法并返回一个随机数:

public int getRandomNumberUsingInts(int min, int max) {
    Random random = new Random();
    return random.ints(min, max)
      .findFirst()
      .getAsInt();
}

同样取值区间[min,max),左闭右开。

3. 在排除某些值的情况下生成随机数

我们还可以在指定范围内生成随机数,同时排除某些值。

3.1. 使用 Math.random()

让我们使用 Math.random() 生成一个在指定范围内排除某些值的随机数:

static int getRandomWithExclusionUsingMathRandom(int min, int max, int [] exclude) {
    Arrays.sort(exclude);
    int random = min + (int) ((max - min + 1 - exclude.length) * Math.random());
    for (int ex : exclude) {
        if (random < ex) {
            break;
        }
        random++;
    }
    return random;
}

`exclude 数组表示需要排除的值。

此外,我们对数组进行升序排序以优化循环。通过排序数组,我们可以确保一旦找到一个大于随机数的排除值,我们就不会再找到,并提前结束循环。如果数组未排序,循环可能会过早结束。

下面一步步分析代码。 为了确保 random 值不在 exclude 数组中。假设我们有一个包含排除值的数组和一个随机数:

int[] exclude = {2, 3, 5};
int random = 3;

接下来,我们遍历数组并与 random 数字进行比较:

for (int ex : exclude) {
    if (random < ex) {
        break;
    }
    random++;
}
return random;

首先,算法开始将 random 值与 exclude 数组的第一个元素进行比较。由于 random 值不大于数组的第一个元素,循环继续并将 random 数字递增到 4。

然后,循环移到下一个元素,即 3。由于 random 数字不大于 3,循环继续,将 random 数字递增到 5。

接下来,数组中的下一个值是 5,它等于 random 数字。循环将 random 数字递增到 6,然后停止,因为我们已经到达数组的末尾。因此,返回的 random 数字是 6。

值得注意的是,如果 random 值小于数组中的任何元素,循环将结束并返回当前的 random 值。

在下一节中,我们将使用 java.util.Random.nextInt() 方法实现相同的算法。

3.2. 使用 Random.nextInt()

前面我们已经掌握了如何使用 java.util.Random.nextInt() 生成指定范围内的随机数。现在,我们来实现如何排除某些数值:

static int getRandomNumberWithExclusionUsingNextInt(int min, int max, int [] exclude) {
    Random rnd = new Random();
    Arrays.sort(exclude);
    int random = min + rnd.nextInt(max - min + 1 - exclude.length);
    for (int ex : exclude) {
        if (random < ex) {
            break;
        }
        random++;
    }
    return random;
}

3.3. 使用 Random.ints()

使用 java.util.Random.ints() 方法生成排除某些值的随机数:

int getRandomWithExclusion(int min, int max, int [] exclude) {
    Random rnd = new Random();
    OptionalInt random = rnd.ints(min, max + 1)
      .filter(num -> Arrays.stream(exclude).noneMatch(ex -> num == ex))
      .findFirst();
    return random.orElse(start);
}

上述代码生成了指定范围内的随机整数流。然后,我们使用 Stream API 的 filter() 方法过滤 exclude 数组中的数字。

最后,我们使用 findFirst() 方法获取流中不在 exclude 数组中的一个数字。

4. 总结

在这篇文章中,我们了解了在指定范围内生成随机数的不同方法。

惯例,代码示例可以在 GitHub 上找到。