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

当前回答

我正在考虑使用以下方法将生成的随机数线性归一化到所需范围。设x为随机数,设a和b为期望归一化数的最小和最大范围。

下面是一个非常简单的代码片段,用来测试线性映射产生的范围。

public static void main(String[] args) {
    int a = 100;
    int b = 1000;
    int lowest = b;
    int highest = a;
    int count = 100000;
    Random random = new Random();
    for (int i = 0; i < count; i++) {
        int nextNumber = (int) ((Math.abs(random.nextDouble()) * (b - a))) + a;
        if (nextNumber < a || nextNumber > b) {
            System.err.println("number not in range :" + nextNumber);
        }
        else {
            System.out.println(nextNumber);
        }
        if (nextNumber < lowest) {
            lowest = nextNumber;
        }
        if (nextNumber > highest) {
            highest = nextNumber;
        }
    }
    System.out.println("Produced " + count + " numbers from " + lowest
            + " to " + highest);
}

其他回答

注意,该方法比下一个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))

要生成“介于两个数字之间”的随机数,请使用以下代码:

Random r = new Random();
int lowerBound = 1;
int upperBound = 11;
int result = r.nextInt(upperBound-lowerBound) + lowerBound;

这将为您提供一个介于1(含)和11(不含)之间的随机数,因此通过添加1来初始化上限值。例如,如果要生成1到10之间的随机数,则使用11而不是10初始化上限数。

一般使用java.utilforRandom。

您可以定义最小和最大范围以获得这些结果。

Random rand=new Random();
rand.nextInt((max+1) - min) + min;

如果你不想重新发明轮子,这里有一个简单明了的解决方案:

RandomStringUtils.randomNumeric(count); // Where count is the number of digits you want in the random number.

Apache Commons,例如组件Lang中的RandomUtils,提供了许多选项来生成任意格式的随机数。

下面是一个简单的示例,它显示了如何从闭合的[min,max]范围生成随机数,而min<=max为真

您可以将其作为孔中字段类重用,也可以将所有Random.class方法放在一个位置

结果示例:

RandomUtils random = new RandomUtils();
random.nextInt(0, 0); // returns 0
random.nextInt(10, 10); // returns 10
random.nextInt(-10, 10); // returns numbers from -10 to 10 (-10, -9....9, 10)
random.nextInt(10, -10); // throws assert

来源:

import junit.framework.Assert;
import java.util.Random;

public class RandomUtils extends Random {

    /**
     * @param min generated value. Can't be > then max
     * @param max generated value
     * @return values in closed range [min, max].
     */
    public int nextInt(int min, int max) {
        Assert.assertFalse("min can't be > then max; values:[" + min + ", " + max + "]", min > max);
        if (min == max) {
            return max;
        }

        return nextInt(max - min + 1) + min;
    }
}