java.util.Random有多好?

java.util.Random有多好?,java,random,Java,Random,两个问题: 每种种子我都会得到不同的数字序列吗 有一些“死”种子吗?(产生零或快速重复的。) 顺便问一下,如果有的话,我应该使用哪些其他PRNG 解决方案:因为我将使用PRNG制作一个游戏,所以我不需要它具有加密安全性。我将使用Mersenne捻线机,因为它的速度快,周期长。这在中有描述。线性同余生成器在理论上已被很好地理解,有关它们的大量资料可在文献和互联网上找到。具有相同参数的线性同余发生器总是输出相同的周期序列,而seed唯一决定的是序列的起始位置。因此,第一个问题的答案是“是的,如果您生

两个问题:

每种种子我都会得到不同的数字序列吗

有一些“死”种子吗?(产生零或快速重复的。)

顺便问一下,如果有的话,我应该使用哪些其他PRNG


解决方案:因为我将使用PRNG制作一个游戏,所以我不需要它具有加密安全性。我将使用Mersenne捻线机,因为它的速度快,周期长。

这在中有描述。线性同余生成器在理论上已被很好地理解,有关它们的大量资料可在文献和互联网上找到。具有相同参数的线性同余发生器总是输出相同的周期序列,而seed唯一决定的是序列的起始位置。因此,第一个问题的答案是“是的,如果您生成了足够多的随机数。”

正如zvrba所说,JavaDoc解释了正常的实现。有相当数量的信息,并提到,这是不被视为加密安全,但非常快,并有各种各样的。(最后一个链接有两个实现——我相信还有其他可用的实现。)


如果您需要加密安全的生成,请阅读Wikipedia页面-有各种可用的选项。

随着RNG的发展,Sun的实现是安全的,但对于大多数目的来说已经足够好了。如果您需要用于加密目的的随机数,如果您只是想要比java.util.random更快更好的东西,那么很容易在网上找到Mersenne Twister的java实现。

如果RNG质量对您来说真的很重要,我建议您使用自己的RNG。也许java.util.Random非常棒,在这个版本中,在您的操作系统上,等等。它可能是。但这可能会改变。以前发生过这样的事,图书馆的作者在后来的版本中把事情弄得更糟

写自己的很简单,然后你就知道到底发生了什么。它在升级时不会改变,等等。这里有一个你可以在10分钟内移植到Java的端口。如果你从现在起一周后开始用某种新语言写作,你可以再次移植它

如果您没有实现自己的RNG,您可以从著名的源代码中获取著名RNG的代码,并将其用于您的项目中。那么没人会把你的发电机从你下面换下来


(我并不主张人们提出自己的算法,只提出自己的实现。包括我在内的大多数人都没有必要开发自己的算法。编写一个你认为很棒的糟糕生成器是很容易的。这就是为什么人们需要问这样的问题,想知道库生成器有多好我引用的生成器中的算法已经通过了许多同行的审查。)

在某种程度上,随机数生成器是课程的马匹。random类使用合理选择的参数实现LCG。但它仍然显示出以下特性:

  • 相当短的时间(2^48)
  • 位不是同样随机的(参见我的文章)
  • 将只生成一小部分值的组合(著名的“”问题)
如果这些东西对你来说无关紧要,那么Random有一个弥补的功能,就是作为JDK的一部分提供。它对于休闲游戏(但不是涉及金钱的游戏)来说已经足够好了。它本身没有脆弱的种子

另一个备选方案是,可以用Java实现,如下所示:

public long randomLong() {
  x ^= (x << 21);
  x ^= (x >>> 35);
  x ^= (x << 4);
  return x;
}
public long random long(){
x^=(x>>35);

x^=(x见我博客文章中的答案:

Random的状态有一个最大周期(一个很长的周期,即2^64个周期)。这可以直接推广到2^k-根据需要投入任意多的状态位,就可以得到最大周期。相比之下,2 Mersenne Twister实际上有一个非常短的周期(参见上述博客文章中的评论)


--哎呀,Random将其自身限制为48位,而不是使用long的完整64位,因此相应地,它的周期毕竟是2^48,而不是2^64。

我不同意编写自己的生成器的想法-这就像编写自己的加密例程:除非你真的非常擅长数学,并且非常仔细地执行,否则它将被禁用这很可能很糟糕。有许多经过仔细研究的算法已经被实现。事实上,正如你在文章中指出的:“随机数生成是一项棘手的工作。好的随机数生成算法很难发明。实现算法的代码很难测试。”为什么要重新发明轮子?(我并不是说你不能设计/实施你自己的PRNG。但作为一名研究统计学家,你有一点领先:)我不认为实现一个RNG有那么神秘。算法是神秘的,但我认为只要有一个清晰的描述,凡人都能正确地编码。顺便说一句:java.lang.Random的算法不会改变。实际的算法和LCG参数是规范的一部分。它不是2^48,而是2^64。不,老实说,它是2^48!!不要相信你在博客上读到的所有东西——看看java.lang.Random的实际源代码!看下面的一行:seed=(seed*multiplier+0xbL)和((1L是的,你是对的,纠正了它。最后错过了掩码。无论如何,那里仍然有有用的信息——seed=(seed*multiplier+add)的周期完全不明显这是我的博客,我倾向于相信我写的:)组合多个生成器实际上是一个很好的方法,在你重复数值之前,它会以一个意想不到的小循环结束。是的!D.克努特,《计算机编程的艺术》,第2卷:(3.2.2)“与随机数生成相关的常见谬误之一是,我们可以使用一个好的生成器并对其稍加修改,以获得一个“更随机”的序列。这通常是错误的……新序列的随机性可能要小得多。总的来说