如何在特定范围内生成随机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`.

当前回答

我将简单地说明问题提供的解决方案有什么问题,以及错误的原因。

解决方案1:

randomNum = minimum + (int)(Math.random()*maximum); 

问题:randomNum分配的值大于最大值。

解释:假设我们的最小值是5,而你的最大值是10。Math.random()中任何大于0.6的值都将使表达式的计算结果为6或更大,加上5将使其大于10(最大值)。问题是你将随机数乘以最大值(这会产生一个几乎和最大值一样大的数字),然后再加上最小值。除非最小值是1,否则它是不正确的。如其他答案所述,您必须切换到

randomNum = minimum + (int)(Math.random()*(maximum-minimum+1))

+1是因为Math.random()永远不会返回1.0。

解决方案2:

Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum =  minimum + i;

这里的问题是,如果第一项小于0,“%”可能会返回负数。由于rn.nextInt()以约50%的概率返回负值,因此也不会得到预期的结果。

然而,这几乎是完美的。您只需进一步查看Javadoc,nextInt(int n)。使用该方法

Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt(n);
randomNum =  minimum + i;

也将返回所需的结果。

其他回答

您可以编辑第二个代码示例以:

Random rn = new Random();
int range = maximum - minimum + 1;
int randomNum =  rn.nextInt(range) + minimum;

您可以在Java 8中简洁地实现这一点:

Random random = new Random();

int max = 10;
int min = 5;
int totalNumber = 10;

IntStream stream = random.ints(totalNumber, min, max);
stream.forEach(System.out::println);

最好使用SecureDrandom,而不仅仅是Random。

public static int generateRandomInteger(int min, int max) {
    SecureRandom rand = new SecureRandom();
    rand.setSeed(new Date().getTime());
    int randomNum = rand.nextInt((max - min) + 1) + min;
    return randomNum;
}
public static Random RANDOM = new Random(System.nanoTime());

public static final float random(final float pMin, final float pMax) {
    return pMin + RANDOM.nextFloat() * (pMax - pMin);
}
int random = minimum + Double.valueOf(Math.random()*(maximum-minimum )).intValue();

或者看看Apache Commons的RandomUtils。