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

当前回答

您可以在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);

其他回答

范围[最小值最大值](含)内的随机数:

int randomFromMinToMaxInclusive = ThreadLocalRandom.current()
        .nextInt(min, max + 1);

我发现这个例子生成随机数:


此示例生成特定范围内的随机整数。

import java.util.Random;

/** Generate random integers in a certain range. */
public final class RandomRange {

  public static final void main(String... aArgs){
    log("Generating random integers in the range 1..10.");

    int START = 1;
    int END = 10;
    Random random = new Random();
    for (int idx = 1; idx <= 10; ++idx){
      showRandomInteger(START, END, random);
    }

    log("Done.");
  }

  private static void showRandomInteger(int aStart, int aEnd, Random aRandom){
    if ( aStart > aEnd ) {
      throw new IllegalArgumentException("Start cannot exceed End.");
    }
    //get the range, casting to long to avoid overflow problems
    long range = (long)aEnd - (long)aStart + 1;
    // compute a fraction of the range, 0 <= frac < range
    long fraction = (long)(range * aRandom.nextDouble());
    int randomNumber =  (int)(fraction + aStart);    
    log("Generated : " + randomNumber);
  }

  private static void log(String aMessage){
    System.out.println(aMessage);
  }
} 

此类的示例运行:

Generating random integers in the range 1..10.
Generated : 9
Generated : 3
Generated : 3
Generated : 9
Generated : 4
Generated : 1
Generated : 3
Generated : 9
Generated : 10
Generated : 10
Done.

在java-8中,他们在Random类中引入了方法int(int randomNumberOrigin,int randomNumber Bound)。

例如,如果要生成[0,10]范围内的五个随机整数(或单个整数),只需执行以下操作:

Random r = new Random();
int[] fiveRandomNumbers = r.ints(5, 0, 11).toArray();
int randomNumber = r.ints(1, 0, 11).findFirst().getAsInt();

第一个参数仅指示生成的IntStream的大小(这是生成无限IntStream的重载方法)。

如果需要执行多个单独的调用,可以从流中创建无限基元迭代器:

public final class IntRandomNumberGenerator {

    private PrimitiveIterator.OfInt randomIterator;

    /**
     * Initialize a new random number generator that generates
     * random numbers in the range [min, max]
     * @param min - the min value (inclusive)
     * @param max - the max value (inclusive)
     */
    public IntRandomNumberGenerator(int min, int max) {
        randomIterator = new Random().ints(min, max + 1).iterator();
    }

    /**
     * Returns a random number in the range (min, max)
     * @return a random number in the range (min, max)
     */
    public int nextInt() {
        return randomIterator.nextInt();
    }
}

您也可以对双值和长值执行此操作。

另一种选择是使用Apache Commons:

import org.apache.commons.math.random.RandomData;
import org.apache.commons.math.random.RandomDataImpl;

public void method() {
    RandomData randomData = new RandomDataImpl();
    int number = randomData.nextInt(5, 10);
    // ...
 }

注意,该方法比下一个Int方法更偏向且效率更低,https://stackoverflow.com/a/738651/360211

实现这一点的一个标准模式是:

Min + (int)(Math.random() * ((Max - Min) + 1))

Java Math库函数Math.random()生成范围[0,1)内的双精度值。请注意,此范围不包括1。

为了首先获得特定的值范围,需要乘以要覆盖的值范围的大小。

Math.random() * ( Max - Min )

这将返回范围[0,Max Min)内的值,其中不包括“Max Min”。

例如,如果需要[5,10),则需要覆盖五个整数值,以便使用

Math.random() * 5

这将返回范围为[0.5)的值,其中不包括5。

现在,您需要将此范围移动到目标范围。您可以通过添加“最小值”值来实现此操作。

Min + (Math.random() * (Max - Min))

现在,您将获得范围为[Min,Max)的值。按照我们的示例,这意味着[5,10):

5 + (Math.random() * (10 - 5))

但是,这仍然不包括Max,您将得到双倍的值。为了获得包含的最大值,您需要向范围参数(Max-Min)添加1,然后通过强制转换为int来截断小数部分。这可以通过以下方式实现:

Min + (int)(Math.random() * ((Max - Min) + 1))

在[Min,Max]范围内的随机整数值,或者按照示例[5,10]:

5 + (int)(Math.random() * ((10 - 5) + 1))