Java:(new Random()).nextInt(5) 可以总是返回相同的数字吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1045013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: Can (new Random()).nextInt(5) always return the same number?
提问by serg
Sometimes this piece of code always returns the same number (and sometimes it works fine):
有时这段代码总是返回相同的数字(有时它工作正常):
(new Random()).nextInt(5)
I have suspicions where the problem is - it probably always creates a new Random with the same seed. So what would be the best solution:
我怀疑问题出在哪里 - 它可能总是用相同的种子创建一个新的 Random 。那么最好的解决方案是什么:
- create a static var for Random() and use it instead.
- use Math.random() * 5 (looks like it uses a static var internally)
- 为 Random() 创建一个静态变量并使用它。
- 使用 Math.random() * 5 (看起来它在内部使用静态变量)
or something else? I don't need anything fancy just something that looks random.
或者是其他东西?我不需要任何花哨的东西,只是看起来随机的东西。
Also it would be helpful if someone can explain why the original code sometimes works and sometimes it doesn't.
如果有人可以解释为什么原始代码有时有效而有时无效,这也会很有帮助。
Thanks.
谢谢。
回答by skaffman
The javadoc for java.util.Random is clear:
java.util.Random 的 javadoc 很清楚:
If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers.
如果使用相同的种子创建 Random 的两个实例,并且对每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列。
The default constructor is also clear:
默认构造函数也很明确:
Creates a new random number generator. This constructor sets the seed of the random number generator to a value very likely to be distinct from any other invocation of this constructor.
创建一个新的随机数生成器。此构造函数将随机数生成器的种子设置为一个很可能与此构造函数的任何其他调用不同的值。
In other words, no guarantees.
换句话说,没有保证。
If you need a more random algorithm, use java.security.SecureRandom.
如果您需要更随机的算法,请使用 java.security.SecureRandom。
回答by Jorn
The Javadoc for Randomisn't explicit about this, but the seed it uses is probably dependent on the current system time. It does state the random numbers will be the same for the same seed. If you use the call within the same millisecond, it will use the same seed. The best solution is probably to use a static Random object and use it for subsequent calls to the method.
Random的 Javadoc没有明确说明这一点,但它使用的种子可能取决于当前系统时间。它确实说明了相同种子的随机数将是相同的。如果您在同一毫秒内使用该调用,它将使用相同的种子。最好的解决方案可能是使用静态 Random 对象并将其用于后续调用该方法。
回答by Bill the Lizard
If you're calling that line of code on successive lines, then yes, the two Random instances you're creating could be created with the same seed from the clock (the clock millisecond tick count is the default seed for Random objects). Almost universally, if an application needs multiple random numbers, you'd create one instance of Random and re-use it as often as you need.
如果您在连续行上调用那行代码,那么是的,您创建的两个 Random 实例可以使用时钟中的相同种子创建(时钟毫秒滴答计数是 Random 对象的默认种子)。几乎普遍而言,如果应用程序需要多个随机数,您可以创建一个 Random 实例并根据需要多次重复使用它。
Edit: Interesting note, The javadoc for Randomhas changed since 1.4.2, which explained that the clock is used as the default seed. Apparently, that's no longer a guarantee.
编辑:有趣的注释,Random的javadoc自 1.4.2 以来发生了变化,这解释了时钟被用作默认种子。显然,这不再是一种保证。
Edit #2: By the way, even with a properly seeded Random instance that you re-use, you'll still get the same random number as the previous call about 1/5 of the time when you call nextInt(5)
.
编辑 #2:顺便说一句,即使使用了正确播种的 Random 实例,您仍然会在调用nextInt(5)
.
public static void main(String[] args) {
Random rand = new Random();
int count = 0;
int trials = 10000;
int current;
int previous = rand.nextInt(5);
for(int i=0; i < trials; ++i)
{
current = rand.nextInt(5);
if( current == previous )
{
count++;
}
}
System.out.println("Random int was the same as previous " + count +
" times out of " + trials + " tries.");
}
回答by OscarRyz
...Sometimes this piece of code [..] returns the same number (and sometimes it works fine)...
...有时这段代码 [..] 返回相同的数字(有时它工作正常)...
So it works randomly??? :) :) :)
所以它随机工作???:) :) :)
Ok, ok, downvote me now!!
好的,好的,现在投票给我!!
回答by erickson
In Java 1.4, the default seed of of a new Random
instance was specified in the API documentation to be the result of System.currentTimeMillis()
. Obviously, a tight loop could create many Random()
instances per tick, all having the same seed and all producing the same psuedo-random sequence. This was especially bad on some platforms, like Windows, where the clock resolution was poor (10 ms or greater).
在 Java 1.4 中,新Random
实例的默认种子在 API 文档中指定为System.currentTimeMillis()
. 显然,一个紧密的循环可以在Random()
每个滴答声中创建许多实例,所有实例都具有相同的种子并产生相同的伪随机序列。这在某些平台上尤其糟糕,例如 Windows,其中时钟分辨率很差(10 毫秒或更高)。
Since Java 5, however, the seed is set "to a value very likely to be distinct" for each invocation of the default constructor. With a different seed for each Random
instance, results should appear random as desired.
然而,从 Java 5 开始,对于默认构造函数的每次调用,种子被设置为“一个很可能不同的值”。对于每个Random
实例使用不同的种子,结果应该根据需要随机出现。
回答by Chuck Daniels
The best way to approximate uniform distribution is to use the static method Random.nextInt(n) to produce integers in the range [0, n-1] (Yes, n is excluded). In your particular example, if you want integers in the range 0 to 5, inclusive, you would call Random.nextInt(6).
近似均匀分布的最佳方法是使用静态方法 Random.nextInt(n) 生成 [0, n-1] 范围内的整数(是的,不包括 n)。在您的特定示例中,如果您想要 0 到 5(含)范围内的整数,您可以调用 Random.nextInt(6)。