如何在特定范围内生成随机int值?

以下方法存在与整数溢出相关的错误:

randomNum = minimum + (int)(Math.random() * maximum);
// Bug: `randomNum` can be bigger than `maximum`.
Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum =  minimum + i;
// Bug: `randomNum` can be smaller than `minimum`.

当前回答

为了避免重复多次所说的内容,我为那些需要加密更强的伪随机数生成器的人展示了一种替代方法,方法是使用SecureRandom类,该类扩展了random类。从源代码中可以看到:

此类提供加密强随机数生成器(RNG)。密码强随机数最小符合使用FIPS中指定的统计随机数生成器测试140-2,加密模块的安全要求,第4.9.1节。此外,SecureRandom必须产生非确定性输出。因此,传递给SecureRandom对象的任何种子材料必须不可预测,并且所有SecureRandom输出序列必须如RFC 1750:随机性中所述,加密性强安全建议。调用者通过no参数获得SecureRandom实例构造函数或getInstance方法之一:SecureRandom随机=新的SecureRandum();许多SecureRandom实现采用伪随机数生成器的形式(PRNG),这意味着他们使用确定性算法来生成来自真实随机种子的伪随机序列。其他实施方式可以产生真正的随机数,而其他人可以使用组合这两种技术的组合。

要生成介于最小值和最大值之间的随机数,请执行以下操作:

public static int generate(SecureRandom secureRandom, int min, int max) {
        return min + secureRandom.nextInt((max - min) + 1);
}

对于给定的最小(含)和最大(不含)值:

return min + secureRandom.nextInt((max - min));

运行代码示例:

public class Main {

    public static int generate(SecureRandom secureRandom, int min, int max) {
        return min + secureRandom.nextInt((max - min) + 1);
    }

    public static void main(String[] arg) {
        SecureRandom random = new SecureRandom();
        System.out.println(generate(random, 0, 2 ));
    }
}

stackoverflow、baeldung、极客等来源提供了Random和SecureRandom类之间的比较。

从baeldung可以看到:

使用SecureRandom最常见的方法是生成int、long、,浮点、双精度或布尔值:int randomInt=secureRandom.nextInt();long randomLong=secureRandom.netLong();float randomFloat=secureRandom.netFloat();doublerandomDouble=secureRandom.nexDouble();boolean randomBoolean=secureRandom.nextBoolean();为了生成int值,我们可以传递一个上界作为参数:int randomInt=secureRandom.nextInt(上限);此外,我们可以为int、double和long生成一个值流:IntStream randomIntStream=secureRandom.ints();LongStream randomLongStream=secureRandom.long();DoubleStream randomDoubleStream=secureRandom.doubles();对于所有流,我们可以显式设置流大小:IntStream IntStream=secureRandom.ints(streamSize);

该类提供了几个其他选项(例如,选择基础随机数生成器),这些选项超出了本问题的范围。

其他回答

以前的大多数建议都不考虑“溢出”。例如:min=整数.min_VALUE,max=100。到目前为止,我采用的正确方法之一是:

final long mod = max- min + 1L;
final int next = (int) (Math.abs(rand.nextLong() % mod) + min);

您可以使用以下方法来执行此操作:

int range = 10;
int min = 5
Random r = new Random();
int = r.nextInt(range) + min;
Random rng = new Random();
int min = 3;
int max = 11;
int upperBound = max - min + 1; // upper bound is exclusive, so +1
int num = min + rng.nextInt(upperBound);
System.out.println(num);

下面是一个函数,它按照用户42155的请求,在lowerBoundIncluded和upperBoundIncluded定义的范围内返回一个整数随机数

SplitableRandom splitableRandom=新的Splitablerandom();

BiFunction<Integer,Integer,Integer> randomInt = (lowerBoundIncluded, upperBoundIncluded)
    -> splittableRandom.nextInt(lowerBoundIncluded, upperBoundIncluded + 1);

randomInt.apply(…,…);//获取随机数

…或更短,用于一次性生成随机数

new SplittableRandom().nextInt(lowerBoundIncluded, upperBoundIncluded + 1);

如果掷骰子,它将是1到6(而不是0到6)之间的随机数,因此:

face = 1 + randomNumbers.nextInt(6);