问题描述:
如何生成特定范围内的随机 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大洲远程工作机会,探索不一样的工作方式