问题描述:

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

我尝试了以下方法,但这些都不起作用:

尝试1:

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

错误:randomNum 可能大于 maximum。

尝试2:

Random rn = new Random();

int n = maximum - minimum + 1;

int i = rn.nextInt() % n;

randomNum = minimum + i;

错误:randomNum 可以小于 minimum。

解决方案1:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

在 Java 1.7 或更高版本中,执行此操作的标准方法如下:

import java.util.concurrent.ThreadLocalRandom;

// nextInt is normally exclusive of the top value,

// so add 1 to make it inclusive

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

请参阅the relevant JavaDoc。这种方法的优点是不需要显式初始化 java.util.Random 实例,如果使用不当,可能会造成混淆和错误。

然而,相反,没有办法明确设置种子,因此在测试或保存游戏状态或类似情况等有用的情况下,很难重现结果。在这些情况下,可以使用下面所示的 Java 1.7 之前的技术。

在 Java 1.7 之前,执行此操作的标准方法如下:

import java.util.Random;

/**

* Returns a pseudo-random number between min and max, inclusive.

* The difference between min and max can be at most

* Integer.MAX_VALUE - 1.

*

* @param min Minimum value

* @param max Maximum value. Must be greater than min.

* @return Integer between min and max, inclusive.

* @see java.util.Random#nextInt(int)

*/

public static int randInt(int min, int max) {

// NOTE: This will (intentionally) not run as written so that folks

// copy-pasting have to think about how to initialize their

// Random instance. Initialization of the Random instance is outside

// the main scope of the question, but some decent options are to have

// a field that is initialized once and then re-used as needed or to

// use ThreadLocalRandom (if using at least Java 1.7).

//

// In particular, do NOT do 'Random rand = new Random()' here or you

// will get not very good / not very random results.

Random rand;

// nextInt is normally exclusive of the top value,

// so add 1 to make it inclusive

int randomNum = rand.nextInt((max - min) + 1) + min;

return randomNum;

}

请参阅the relevant JavaDoc。在实践中,java.util.Random 类通常优于 java.lang.Math.random()。

特别是,当标准库中有一个简单的 API 来完成任务时,不需要重新发明随机整数生成轮。

对于 max 值为 Integer.MAX_VALUE 的调用,可能会溢出,导致 java.lang.IllegalArgumentException。您可以尝试使用:randInt(0, Integer.MAX_VALUE)。此外,如果 nextInt((max-min) + 1) 返回最高值(我认为非常罕见)它不会再次溢出(假设 min 和 max 是足够高的值)?如何处理这种情况?

现在有 nextLong(long origin, long bound) 可用。发帖供参考。我不知道它在发布时是否在那里。

解决方案2:

huntsbot.com提供全网独家一站式外包任务、远程工作、创意产品分享与订阅服务!

请注意,与 nextInt 方法 https://stackoverflow.com/a/738651/360211 相比,此方法更偏颇且效率更低

实现此目的的一种标准模式是:

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

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

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

Math.random() * ( Max - Min )

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

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

Math.random() * 5

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

现在您需要将此范围向上移动到您的目标范围。您可以通过添加 Min 值来做到这一点。

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

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

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

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

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

你有它。范围 [Min,Max] 或示例 [5,10] 中的随机整数值:

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

Sun 文档明确指出,如果需要 int 而不是 Math.random() 生成双精度值,则最好使用 Random()。

与 nextInt 方法相比,这实际上是有偏差的 stackoverflow.com/a/738651/360211

在这种情况下,“有偏见”意味着在执行 2^53 次后,一些数字平均会多出一次。

即使我也使用它,我想指出这不是一个真正的随机数。这就是为什么它不应该用于任何安全功能。但对于任何偶然的情况,这是最直接的方法。

解决方案3:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

利用:

Random ran = new Random();

int x = ran.nextInt(6) + 5;

整数 x 现在是可能结果为 5-10 的随机数。

解决方案4:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

利用:

minValue + rn.nextInt(maxValue - minValue + 1)

解决方案5:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

对于 java-8,他们在 Random 类中引入了方法 ints(int randomNumberOrigin, int randomNumberBound)。

例如,如果您想在 [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();

}

}

您也可以对 double 和 long 值执行此操作。我希望它有帮助! 

我建议您仅将 randomIterator 实例化一次。请参阅 Greg Case 对他自己的回答的评论。

解决方案6:

huntsbot.com – 程序员副业首选,一站式外包任务、远程工作、创意产品分享订阅平台。

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

Random rn = new Random();

int range = maximum - minimum + 1;

int randomNum = rn.nextInt(range) + minimum;

解决方案7:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

只需对您的第一个解决方案进行小修改就足够了。

Random rand = new Random();

randomNum = minimum + rand.nextInt((maximum - minimum) + 1);

在此处查看更多关于 Random 的实施

对于最小值 <= 值 < 最大值,我对 Math 做了同样的事情:randomNum = minimum + (int)(Math.random() * (maximum-minimum));但是演员阵容并不是很好看;)

至少迟到 7 年重复答案。

作为初学者,这对我来说是最容易实现的。谢谢!

解决方案8:

与HuntsBot一起,探索全球自由职业机会–huntsbot.com

ThreadLocalRandom 等效于多线程环境的类 java.util.Random。在每个线程中本地执行随机数的生成。因此,通过减少冲突,我们可以获得更好的性能。

int rand = ThreadLocalRandom.current().nextInt(x,y);

x,y - 间隔,例如 (1,10)

解决方案9:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

Java 中的 Math.Random 类是从 0 开始的。所以,如果你写这样的东西:

Random rand = new Random();

int x = rand.nextInt(10);

x 将介于 0-9 之间。

因此,给定以下 25 项数组,在 0(数组的基数)和 array.length 之间生成随机数的代码将是:

String[] i = new String[25];

Random rand = new Random();

int index = 0;

index = rand.nextInt( i.length );

由于 i.length 将返回 25,因此 nextInt( i.length ) 将返回一个介于 0-24 范围内的数字。另一个选项与 Math.Random 一起使用,其工作方式相同。

index = (int) Math.floor(Math.random() * i.length);

为了更好地理解,请查看论坛帖子Random Intervals (archive.org)。

这让我感到困惑,为什么您将索引实例化为 0。

@CodeConfident index 变量不会影响随机数的结果。您可以选择以任何方式初始化它,而不必担心改变结果。希望这可以帮助。

没错……完全没用过。我会直接将其初始化为 rand:int index = rand.nextInt(i.Length);

或者根本没有。 int index; \n index = rand... 如果一个人喜欢在不同的行上声明和赋值。一些编码标准比其他编码标准更严格(并且没有明显的目的)。

解决方案10:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

只需执行以下语句即可完成:

Randomizer.generate(0, 10); // Minimum of zero and maximum of ten

下面是它的源代码。

文件 Randomizer.java

public class Randomizer {

public static int generate(int min, int max) {

return min + (int)(Math.random() * ((max - min) + 1));

}

}

它既干净又简单。

这可能是对另一个示例的编辑,现在它只是一个公然的声誉副本。指出“得票最多的答案”也不是很直接,它可以改变。

没错@MaartenBodewes。当我写这个答案时,the answer with the most votes above 仍然被写成类似算法的解决方案。现在,上面的解决方案已经发生了很大变化,现在这个答案看起来像一个模仿猫。

我真的不明白为什么这些基本代码不是 Java 标准库的一部分。为什么我必须实现这个?

解决方案11:

huntsbot.com高效搞钱,一站式跟进超10+任务平台外包需求

请原谅我的挑剔,但大多数人建议的解决方案,即 min + rng.nextInt(max - min + 1)),似乎很危险,因为:

rng.nextInt(n) 无法达到 Integer.MAX_VALUE。

(max - min) min 为负数时可能会导致溢出。

一个万无一失的解决方案将为 [Integer.MIN_VALUE, Integer.MAX_VALUE] 中的任何 min <= max 返回正确的结果。考虑以下简单的实现:

int nextIntInRange(int min, int max, Random rng) {

if (min > max) {

throw new IllegalArgumentException("Cannot draw random int from invalid range [" + min + ", " + max + "].");

}

int diff = max - min;

if (diff >= 0 && diff != Integer.MAX_VALUE) {

return (min + rng.nextInt(diff + 1));

}

int i;

do {

i = rng.nextInt();

} while (i < min || i > max);

return i;

}

尽管效率低,但请注意 while 循环中的成功概率始终为 50% 或更高。

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

当差异 = Integer.MAX_VALUE 时,为什么不抛出 IllegalArgumentException?那么你就不需要while循环了。

@mpkorstanje 此实现旨在使用 min <= max 的任何值,即使它们的差异等于或大于 MAX_VALUE。在这种情况下,运行一个循环直到成功是一种常见模式,以保证均匀分布(如果随机性的底层来源是均匀的)。当参数不是 2 的幂时,Random.nextInt(int) 在内部执行。

原文链接:https://www.huntsbot.com/qa/Yl7W/how-do-i-generate-random-integers-within-a-specific-range-in-java?lang=zh_CN

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: